642 lines
29 KiB
JavaScript
642 lines
29 KiB
JavaScript
let currentWeekStart = null;
|
||
|
||
const weekdays = ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье'];
|
||
const weekdaysShort = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'];
|
||
|
||
function getTodayInLondon() {
|
||
// Получаем текущую дату в таймзоне London
|
||
const now = new Date();
|
||
const formatter = new Intl.DateTimeFormat('en-CA', {
|
||
timeZone: 'Europe/London',
|
||
year: 'numeric',
|
||
month: '2-digit',
|
||
day: '2-digit'
|
||
});
|
||
return formatter.format(now);
|
||
}
|
||
|
||
function getWeekStart(dateStr = null) {
|
||
if (!dateStr) {
|
||
dateStr = getTodayInLondon();
|
||
}
|
||
// Создаем дату из строки YYYY-MM-DD в локальном времени
|
||
const [year, month, day] = dateStr.split('-').map(Number);
|
||
const date = new Date(year, month - 1, day);
|
||
// getDay() возвращает 0=воскресенье, 1=понедельник, ..., 6=суббота
|
||
// Находим понедельник текущей недели
|
||
const dayOfWeek = date.getDay();
|
||
// Если воскресенье (0), идем на 6 дней назад, иначе на (dayOfWeek-1) дней назад
|
||
const diff = dayOfWeek === 0 ? -6 : -(dayOfWeek - 1);
|
||
const monday = new Date(date);
|
||
monday.setDate(date.getDate() + diff);
|
||
// Проверяем, что получился понедельник
|
||
if (monday.getDay() !== 1) {
|
||
console.error('Error: getWeekStart did not return Monday!', monday.getDay());
|
||
}
|
||
// Возвращаем в формате YYYY-MM-DD
|
||
const yearStr = monday.getFullYear();
|
||
const monthStr = String(monday.getMonth() + 1).padStart(2, '0');
|
||
const dayStr = String(monday.getDate()).padStart(2, '0');
|
||
return `${yearStr}-${monthStr}-${dayStr}`;
|
||
}
|
||
|
||
function formatDate(dateStr) {
|
||
// Создаем дату из строки YYYY-MM-DD в локальном времени
|
||
const [year, month, day] = dateStr.split('-').map(Number);
|
||
const date = new Date(year, month - 1, day);
|
||
// getDay() возвращает 0=воскресенье, 1=понедельник, ..., 6=суббота
|
||
// Конвертируем в формат где 0=понедельник, 6=воскресенье
|
||
const jsDay = date.getDay();
|
||
const weekdayIndex = jsDay === 0 ? 6 : jsDay - 1; // 0=пн, 6=вс
|
||
return `${weekdaysShort[weekdayIndex]}, ${date.getDate()}`;
|
||
}
|
||
|
||
function formatDateFull(dateStr) {
|
||
// Создаем дату из строки YYYY-MM-DD в локальном времени
|
||
const [year, month, day] = dateStr.split('-').map(Number);
|
||
const date = new Date(year, month - 1, day);
|
||
const months = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня',
|
||
'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'];
|
||
// getDay() возвращает 0=воскресенье, 1=понедельник, ..., 6=суббота
|
||
// Конвертируем в формат где 0=понедельник, 6=воскресенье
|
||
const jsDay = date.getDay();
|
||
const weekdayIndex = jsDay === 0 ? 6 : jsDay - 1; // 0=пн, 6=вс
|
||
return `${weekdays[weekdayIndex]}, ${date.getDate()} ${months[date.getMonth()]}`;
|
||
}
|
||
|
||
function getWeekDates(startDate) {
|
||
// startDate должен быть понедельником (в формате YYYY-MM-DD)
|
||
const dates = [];
|
||
// Создаем дату из строки в локальном времени
|
||
const [year, month, day] = startDate.split('-').map(Number);
|
||
const start = new Date(year, month - 1, day);
|
||
// Убеждаемся, что это понедельник
|
||
const dayOfWeek = start.getDay();
|
||
if (dayOfWeek !== 1) {
|
||
// Если не понедельник, находим понедельник
|
||
const diff = dayOfWeek === 0 ? -6 : -(dayOfWeek - 1);
|
||
start.setDate(start.getDate() + diff);
|
||
}
|
||
// Возвращаем 7 дней: понедельник - воскресенье
|
||
const baseDate = new Date(start);
|
||
for (let i = 0; i < 7; i++) {
|
||
const date = new Date(baseDate);
|
||
date.setDate(baseDate.getDate() + i);
|
||
// Форматируем в YYYY-MM-DD
|
||
const yearStr = date.getFullYear();
|
||
const monthStr = String(date.getMonth() + 1).padStart(2, '0');
|
||
const dayStr = String(date.getDate()).padStart(2, '0');
|
||
dates.push(`${yearStr}-${monthStr}-${dayStr}`);
|
||
}
|
||
// Проверяем, что первый день - понедельник, последний - воскресенье
|
||
const [firstYear, firstMonth, firstDayNum] = dates[0].split('-').map(Number);
|
||
const firstDate = new Date(firstYear, firstMonth - 1, firstDayNum);
|
||
const [lastYear, lastMonth, lastDayNum] = dates[6].split('-').map(Number);
|
||
const lastDate = new Date(lastYear, lastMonth - 1, lastDayNum);
|
||
const firstDay = firstDate.getDay();
|
||
const lastDay = lastDate.getDay();
|
||
if (firstDay !== 1 || lastDay !== 0) {
|
||
console.error('Error: Week should start on Monday and end on Sunday!', {
|
||
first: dates[0], firstDay,
|
||
last: dates[6], lastDay
|
||
});
|
||
}
|
||
return dates;
|
||
}
|
||
|
||
async function loadSchedule() {
|
||
// Убеждаемся, что currentWeekStart - это понедельник
|
||
if (!currentWeekStart) {
|
||
currentWeekStart = getWeekStart();
|
||
} else {
|
||
currentWeekStart = getWeekStart(currentWeekStart);
|
||
}
|
||
|
||
const weekDates = getWeekDates(currentWeekStart);
|
||
const fromDate = weekDates[0];
|
||
const toDate = weekDates[6];
|
||
|
||
// Проверяем, что неделя начинается с понедельника и заканчивается воскресеньем
|
||
const [mondayYear, mondayMonth, mondayDay] = weekDates[0].split('-').map(Number);
|
||
const monday = new Date(mondayYear, mondayMonth - 1, mondayDay);
|
||
const [sundayYear, sundayMonth, sundayDay] = weekDates[6].split('-').map(Number);
|
||
const sunday = new Date(sundayYear, sundayMonth - 1, sundayDay);
|
||
if (monday.getDay() !== 1 || sunday.getDay() !== 0) {
|
||
console.error('Week should start on Monday and end on Sunday! Fixing...', {
|
||
monday: weekDates[0], mondayDay: monday.getDay(),
|
||
sunday: weekDates[6], sundayDay: sunday.getDay()
|
||
});
|
||
// Исправляем автоматически без рекурсии
|
||
currentWeekStart = getWeekStart();
|
||
const correctedWeekDates = getWeekDates(currentWeekStart);
|
||
// Используем исправленные даты напрямую
|
||
const correctedFromDate = correctedWeekDates[0];
|
||
const correctedToDate = correctedWeekDates[6];
|
||
|
||
try {
|
||
const response = await fetch(`/api/schedule?from_date=${correctedFromDate}&to_date=${correctedToDate}`);
|
||
const data = await response.json();
|
||
renderSchedule(correctedWeekDates, data.items);
|
||
document.getElementById('week-range').textContent =
|
||
`${formatDateFull(correctedWeekDates[0])} - ${formatDateFull(correctedWeekDates[6])}`;
|
||
updateWeekNavigationButtons();
|
||
} catch (error) {
|
||
console.error('Error loading schedule:', error);
|
||
}
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`/api/schedule?from_date=${fromDate}&to_date=${toDate}`);
|
||
if (!response.ok) {
|
||
throw new Error(`HTTP error! status: ${response.status}`);
|
||
}
|
||
const data = await response.json();
|
||
|
||
if (!data.items) {
|
||
console.error('Invalid response format:', data);
|
||
return;
|
||
}
|
||
|
||
renderSchedule(weekDates, data.items);
|
||
|
||
// Обновляем заголовок недели
|
||
document.getElementById('week-range').textContent =
|
||
`${formatDateFull(weekDates[0])} - ${formatDateFull(weekDates[6])}`;
|
||
|
||
// Обновляем кнопки навигации
|
||
updateWeekNavigationButtons();
|
||
} catch (error) {
|
||
console.error('Error loading schedule:', error);
|
||
}
|
||
}
|
||
|
||
function renderSchedule(weekDates, items) {
|
||
const grid = document.getElementById('schedule-grid');
|
||
if (!grid) {
|
||
console.error('Schedule grid not found!');
|
||
return;
|
||
}
|
||
grid.innerHTML = '';
|
||
|
||
weekDates.forEach(dateStr => {
|
||
const dayItems = items.filter(item => item.date === dateStr);
|
||
|
||
const column = document.createElement('div');
|
||
column.className = 'day-column';
|
||
|
||
column.innerHTML = `
|
||
<div class="day-header">${formatDateFull(dateStr)}</div>
|
||
<div class="day-items" data-date="${dateStr}">
|
||
${renderDayItems(dayItems)}
|
||
</div>
|
||
`;
|
||
|
||
grid.appendChild(column);
|
||
});
|
||
}
|
||
|
||
function renderDayItems(items) {
|
||
if (items.length === 0) {
|
||
return '<div style="color: #999; font-style: italic; padding: 10px;">Нет записей</div>';
|
||
}
|
||
|
||
const tasks = items.filter(item => item.kind === 'task');
|
||
const events = items.filter(item => item.kind === 'event');
|
||
|
||
let html = '';
|
||
|
||
// Tasks
|
||
tasks.forEach(task => {
|
||
html += `
|
||
<div class="item task" data-id="${task.id}" data-kind="task">
|
||
<div class="item-title">${task.title}</div>
|
||
${task.repeat_weekly ? '<div style="font-size: 11px; color: #FF9800;">Повторяется</div>' : ''}
|
||
<div class="item-actions">
|
||
<button class="btn-edit" onclick="editItem(${task.id}, 'task')">Изменить</button>
|
||
<button class="btn-delete" onclick="deleteItem(${task.id}, 'task')">Удалить</button>
|
||
</div>
|
||
</div>
|
||
`;
|
||
});
|
||
|
||
// Events
|
||
events.sort((a, b) => a.start_time.localeCompare(b.start_time)).forEach(event => {
|
||
const endTime = calculateEndTime(event.start_time, event.duration_min);
|
||
html += `
|
||
<div class="item event" data-id="${event.id}" data-kind="event">
|
||
<div class="item-time">${event.start_time}-${endTime}</div>
|
||
<div class="item-title">${event.title}</div>
|
||
<div class="item-actions">
|
||
<button class="btn-edit" onclick="editItem(${event.id}, 'event')">Изменить</button>
|
||
<button class="btn-delete" onclick="deleteItem(${event.id}, 'event')">Удалить</button>
|
||
</div>
|
||
</div>
|
||
`;
|
||
});
|
||
|
||
return html;
|
||
}
|
||
|
||
function calculateEndTime(startTime, durationMin) {
|
||
const [hour, minute] = startTime.split(':').map(Number);
|
||
const totalMinutes = hour * 60 + minute + durationMin;
|
||
const endHour = Math.floor(totalMinutes / 60);
|
||
const endMinute = totalMinutes % 60;
|
||
return `${String(endHour).padStart(2, '0')}:${String(endMinute).padStart(2, '0')}`;
|
||
}
|
||
|
||
function showModal(content) {
|
||
document.getElementById('modal-body').innerHTML = content;
|
||
document.getElementById('modal').style.display = 'block';
|
||
}
|
||
|
||
function closeModal() {
|
||
document.getElementById('modal').style.display = 'none';
|
||
}
|
||
|
||
function showAddTaskModal(selectedDate = null) {
|
||
const today = getTodayInLondon();
|
||
const todayWeekStart = getWeekStart(today);
|
||
const nextWeekStart = new Date(todayWeekStart + 'T00:00:00');
|
||
nextWeekStart.setDate(nextWeekStart.getDate() + 7);
|
||
const nextWeekStartStr = nextWeekStart.toISOString().split('T')[0];
|
||
|
||
// Ограничиваем выбор дат: только текущая и следующая неделя
|
||
const minDate = todayWeekStart;
|
||
const maxDate = new Date(nextWeekStartStr + 'T00:00:00');
|
||
maxDate.setDate(maxDate.getDate() + 6); // Воскресенье следующей недели
|
||
const maxDateStr = maxDate.toISOString().split('T')[0];
|
||
|
||
const selectedDateObj = selectedDate ? new Date(selectedDate + 'T00:00:00') : new Date(today + 'T00:00:00');
|
||
// getDay() возвращает 0=воскресенье, 1=понедельник, ..., 6=суббота
|
||
// Конвертируем в формат 0=понедельник, 6=воскресенье
|
||
const jsWeekday = selectedDateObj.getDay();
|
||
const selectedWeekday = jsWeekday === 0 ? 6 : jsWeekday - 1; // 0=пн, 6=вс
|
||
const remainingWeekdays = [];
|
||
|
||
// Оставшиеся дни недели после выбранного (среда=2, четверг=3, пятница=4, суббота=5, воскресенье=6)
|
||
for (let i = selectedWeekday + 1; i <= 6; i++) {
|
||
remainingWeekdays.push(i);
|
||
}
|
||
|
||
const content = `
|
||
<h2>Добавить задачу</h2>
|
||
<form id="add-task-form">
|
||
<div class="form-group">
|
||
<label>Дата:</label>
|
||
<input type="date" id="task-date" value="${selectedDate || today}" min="${minDate}" max="${maxDateStr}" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Название:</label>
|
||
<textarea id="task-title" required></textarea>
|
||
</div>
|
||
<div class="form-group">
|
||
<div class="checkbox-group">
|
||
<input type="checkbox" id="task-repeat-weekly">
|
||
<label for="task-repeat-weekly">Повторять каждую неделю</label>
|
||
</div>
|
||
</div>
|
||
<div class="form-group" id="copy-weekdays-group" style="display: none;">
|
||
<label>Добавить на другие дни недели:</label>
|
||
<div class="weekdays-select">
|
||
${remainingWeekdays.map(day => {
|
||
// day в формате 0=пн, 6=вс, но weekdaysShort использует JS формат (0=вс)
|
||
const jsDay = day === 6 ? 0 : day + 1;
|
||
return `
|
||
<label>
|
||
<input type="checkbox" name="copy-weekday" value="${day}">
|
||
${weekdaysShort[jsDay]}
|
||
</label>
|
||
`;
|
||
}).join('')}
|
||
</div>
|
||
</div>
|
||
<div style="margin-top: 20px;">
|
||
<button type="submit" class="btn btn-primary">Добавить</button>
|
||
<button type="button" class="btn" onclick="closeModal()">Отмена</button>
|
||
</div>
|
||
</form>
|
||
`;
|
||
|
||
showModal(content);
|
||
|
||
document.getElementById('task-repeat-weekly').addEventListener('change', function() {
|
||
document.getElementById('copy-weekdays-group').style.display =
|
||
this.checked ? 'none' : 'block';
|
||
});
|
||
|
||
document.getElementById('add-task-form').addEventListener('submit', async (e) => {
|
||
e.preventDefault();
|
||
const date = document.getElementById('task-date').value;
|
||
const title = document.getElementById('task-title').value;
|
||
const repeatWeekly = document.getElementById('task-repeat-weekly').checked;
|
||
const copyWeekdays = Array.from(document.querySelectorAll('input[name="copy-weekday"]:checked'))
|
||
.map(cb => parseInt(cb.value));
|
||
|
||
try {
|
||
const response = await fetch('/api/events?kind=task', {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify({
|
||
date,
|
||
title,
|
||
repeat_weekly: repeatWeekly,
|
||
copy_to_weekdays: copyWeekdays.length > 0 ? copyWeekdays : null
|
||
})
|
||
});
|
||
|
||
if (response.ok) {
|
||
const result = await response.json();
|
||
console.log('Task created:', result);
|
||
closeModal();
|
||
// Небольшая задержка перед обновлением, чтобы БД успела сохранить
|
||
setTimeout(() => {
|
||
loadSchedule().catch(err => console.error('Error reloading schedule:', err));
|
||
}, 100);
|
||
} else {
|
||
const error = await response.json();
|
||
console.error('Error creating task:', error);
|
||
alert('Ошибка: ' + (error.detail || 'Неизвестная ошибка'));
|
||
}
|
||
} catch (error) {
|
||
console.error('Exception creating task:', error);
|
||
alert('Ошибка при добавлении задачи: ' + error.message);
|
||
}
|
||
});
|
||
}
|
||
|
||
function showAddEventModal(selectedDate = null) {
|
||
const today = getTodayInLondon();
|
||
const todayWeekStart = getWeekStart(today);
|
||
const nextWeekStart = new Date(todayWeekStart + 'T00:00:00');
|
||
nextWeekStart.setDate(nextWeekStart.getDate() + 7);
|
||
const nextWeekStartStr = nextWeekStart.toISOString().split('T')[0];
|
||
|
||
// Ограничиваем выбор дат: только текущая и следующая неделя
|
||
const minDate = todayWeekStart;
|
||
const maxDate = new Date(nextWeekStartStr + 'T00:00:00');
|
||
maxDate.setDate(maxDate.getDate() + 6); // Воскресенье следующей недели
|
||
const maxDateStr = maxDate.toISOString().split('T')[0];
|
||
|
||
const content = `
|
||
<h2>Добавить занятие</h2>
|
||
<form id="add-event-form">
|
||
<div class="form-group">
|
||
<label>Дата:</label>
|
||
<input type="date" id="event-date" value="${selectedDate || today}" min="${minDate}" max="${maxDateStr}" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Время начала:</label>
|
||
<div style="display: flex; gap: 10px;">
|
||
<select id="event-hour" required>
|
||
${Array.from({length: 13}, (_, i) => i + 8).map(h =>
|
||
`<option value="${String(h).padStart(2, '0')}">${String(h).padStart(2, '0')}</option>`
|
||
).join('')}
|
||
</select>
|
||
<select id="event-minute" required>
|
||
<option value="00">00</option>
|
||
<option value="15">15</option>
|
||
<option value="30">30</option>
|
||
<option value="45">45</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Длительность:</label>
|
||
<div style="display: flex; gap: 10px;">
|
||
<select id="event-duration-hour">
|
||
<option value="0">0</option>
|
||
<option value="1">1</option>
|
||
<option value="2">2</option>
|
||
<option value="3">3</option>
|
||
</select>
|
||
<select id="event-duration-minute">
|
||
<option value="00">00</option>
|
||
<option value="15">15</option>
|
||
<option value="30">30</option>
|
||
<option value="45">45</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Название:</label>
|
||
<textarea id="event-title" required></textarea>
|
||
</div>
|
||
<div style="margin-top: 20px;">
|
||
<button type="submit" class="btn btn-primary">Добавить</button>
|
||
<button type="button" class="btn" onclick="closeModal()">Отмена</button>
|
||
</div>
|
||
</form>
|
||
`;
|
||
|
||
showModal(content);
|
||
|
||
document.getElementById('add-event-form').addEventListener('submit', async (e) => {
|
||
e.preventDefault();
|
||
const date = document.getElementById('event-date').value;
|
||
const hour = document.getElementById('event-hour').value;
|
||
const minute = document.getElementById('event-minute').value;
|
||
const durHour = parseInt(document.getElementById('event-duration-hour').value);
|
||
const durMin = parseInt(document.getElementById('event-duration-minute').value);
|
||
const title = document.getElementById('event-title').value;
|
||
|
||
const durationMin = durHour * 60 + durMin;
|
||
if (durationMin === 0) {
|
||
alert('Длительность должна быть минимум 15 минут');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch('/api/events?kind=event', {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify({
|
||
date,
|
||
start_time: `${hour}:${minute}`,
|
||
duration_min: durationMin,
|
||
title
|
||
})
|
||
});
|
||
|
||
if (response.ok) {
|
||
const result = await response.json();
|
||
console.log('Event created:', result);
|
||
closeModal();
|
||
// Небольшая задержка перед обновлением, чтобы БД успела сохранить
|
||
setTimeout(() => {
|
||
loadSchedule().catch(err => console.error('Error reloading schedule:', err));
|
||
}, 100);
|
||
} else {
|
||
const error = await response.json();
|
||
console.error('Error creating event:', error);
|
||
alert('Ошибка: ' + (error.detail || 'Неизвестная ошибка'));
|
||
}
|
||
} catch (error) {
|
||
console.error('Exception creating event:', error);
|
||
alert('Ошибка при добавлении занятия: ' + error.message);
|
||
}
|
||
});
|
||
}
|
||
|
||
async function editItem(id, kind) {
|
||
// TODO: Реализовать редактирование
|
||
alert('Редактирование будет реализовано позже');
|
||
}
|
||
|
||
async function deleteItem(id, kind) {
|
||
if (!confirm('Удалить эту запись?')) return;
|
||
|
||
try {
|
||
const response = await fetch(`/api/events/${id}`, {
|
||
method: 'DELETE'
|
||
});
|
||
|
||
if (response.ok) {
|
||
// Небольшая задержка перед обновлением
|
||
setTimeout(() => {
|
||
loadSchedule().catch(err => console.error('Error reloading schedule:', err));
|
||
}, 100);
|
||
} else {
|
||
const error = await response.json();
|
||
alert('Ошибка при удалении: ' + (error.detail || 'Неизвестная ошибка'));
|
||
}
|
||
} catch (error) {
|
||
alert('Ошибка при удалении: ' + error.message);
|
||
console.error(error);
|
||
}
|
||
}
|
||
|
||
function updateWeekNavigationButtons() {
|
||
const today = getTodayInLondon();
|
||
const todayWeekStart = getWeekStart(today);
|
||
|
||
// Вычисляем следующую неделю
|
||
const [year, month, day] = todayWeekStart.split('-').map(Number);
|
||
const nextWeekStartDate = new Date(year, month - 1, day);
|
||
nextWeekStartDate.setDate(nextWeekStartDate.getDate() + 7);
|
||
const nextWeekStartStr = `${nextWeekStartDate.getFullYear()}-${String(nextWeekStartDate.getMonth() + 1).padStart(2, '0')}-${String(nextWeekStartDate.getDate()).padStart(2, '0')}`;
|
||
|
||
// Создаем даты для сравнения
|
||
const [currYear, currMonth, currDay] = currentWeekStart.split('-').map(Number);
|
||
const currentWeekStartDate = new Date(currYear, currMonth - 1, currDay);
|
||
|
||
const [todayYear, todayMonth, todayDay] = todayWeekStart.split('-').map(Number);
|
||
const todayWeekStartDate = new Date(todayYear, todayMonth - 1, todayDay);
|
||
|
||
const [nextYear, nextMonth, nextDay] = nextWeekStartStr.split('-').map(Number);
|
||
const nextWeekStartDateObj = new Date(nextYear, nextMonth - 1, nextDay);
|
||
|
||
// Отключаем кнопку "предыдущая неделя", если уже на текущей неделе
|
||
const prevButton = document.getElementById('prev-week');
|
||
if (currentWeekStartDate.getTime() <= todayWeekStartDate.getTime()) {
|
||
prevButton.disabled = true;
|
||
prevButton.style.opacity = '0.5';
|
||
prevButton.style.cursor = 'not-allowed';
|
||
} else {
|
||
prevButton.disabled = false;
|
||
prevButton.style.opacity = '1';
|
||
prevButton.style.cursor = 'pointer';
|
||
}
|
||
|
||
// Отключаем кнопку "следующая неделя", если уже на следующей неделе
|
||
const nextButton = document.getElementById('next-week');
|
||
if (currentWeekStartDate.getTime() >= nextWeekStartDateObj.getTime()) {
|
||
nextButton.disabled = true;
|
||
nextButton.style.opacity = '0.5';
|
||
nextButton.style.cursor = 'not-allowed';
|
||
} else {
|
||
nextButton.disabled = false;
|
||
nextButton.style.opacity = '1';
|
||
nextButton.style.cursor = 'pointer';
|
||
}
|
||
}
|
||
|
||
// Инициализация
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
currentWeekStart = getWeekStart();
|
||
loadSchedule();
|
||
updateWeekNavigationButtons();
|
||
|
||
document.getElementById('prev-week').addEventListener('click', () => {
|
||
const today = getTodayInLondon();
|
||
const todayWeekStart = getWeekStart(today);
|
||
|
||
// Создаем даты для сравнения
|
||
const [currYear, currMonth, currDay] = currentWeekStart.split('-').map(Number);
|
||
const currentWeekStartDate = new Date(currYear, currMonth - 1, currDay);
|
||
|
||
const [todayYear, todayMonth, todayDay] = todayWeekStart.split('-').map(Number);
|
||
const todayWeekStartDate = new Date(todayYear, todayMonth - 1, todayDay);
|
||
|
||
// Разрешаем только текущую и следующую неделю
|
||
// Если текущая неделя - это сегодняшняя неделя, не разрешаем идти назад
|
||
if (currentWeekStartDate.getTime() <= todayWeekStartDate.getTime()) {
|
||
console.log('Already on current week, cannot go back');
|
||
return; // Уже на текущей неделе, нельзя идти назад
|
||
}
|
||
|
||
// Переходим на предыдущую неделю
|
||
const prevWeekDate = new Date(currYear, currMonth - 1, currDay);
|
||
prevWeekDate.setDate(prevWeekDate.getDate() - 7);
|
||
currentWeekStart = `${prevWeekDate.getFullYear()}-${String(prevWeekDate.getMonth() + 1).padStart(2, '0')}-${String(prevWeekDate.getDate()).padStart(2, '0')}`;
|
||
// Убеждаемся, что это понедельник
|
||
currentWeekStart = getWeekStart(currentWeekStart);
|
||
console.log('Moving to previous week:', currentWeekStart);
|
||
loadSchedule();
|
||
});
|
||
|
||
document.getElementById('next-week').addEventListener('click', () => {
|
||
const today = getTodayInLondon();
|
||
const todayWeekStart = getWeekStart(today);
|
||
|
||
// Вычисляем следующую неделю от текущей
|
||
const [year, month, day] = currentWeekStart.split('-').map(Number);
|
||
const nextWeekDate = new Date(year, month - 1, day);
|
||
nextWeekDate.setDate(nextWeekDate.getDate() + 7);
|
||
const nextWeekStartStr = `${nextWeekDate.getFullYear()}-${String(nextWeekDate.getMonth() + 1).padStart(2, '0')}-${String(nextWeekDate.getDate()).padStart(2, '0')}`;
|
||
|
||
// Вычисляем максимально допустимую следующую неделю (от сегодня)
|
||
const [todayYear, todayMonth, todayDay] = todayWeekStart.split('-').map(Number);
|
||
const maxNextWeekDate = new Date(todayYear, todayMonth - 1, todayDay);
|
||
maxNextWeekDate.setDate(maxNextWeekDate.getDate() + 7);
|
||
const maxNextWeekStr = `${maxNextWeekDate.getFullYear()}-${String(maxNextWeekDate.getMonth() + 1).padStart(2, '0')}-${String(maxNextWeekDate.getDate()).padStart(2, '0')}`;
|
||
|
||
// Разрешаем только текущую и следующую неделю
|
||
if (nextWeekStartStr > maxNextWeekStr) {
|
||
console.log('Already on next week, cannot go further');
|
||
return; // Уже на следующей неделе, нельзя идти дальше
|
||
}
|
||
|
||
// Переходим на следующую неделю
|
||
currentWeekStart = nextWeekStartStr;
|
||
// Убеждаемся, что это понедельник
|
||
currentWeekStart = getWeekStart(currentWeekStart);
|
||
console.log('Moving to next week:', currentWeekStart);
|
||
loadSchedule();
|
||
});
|
||
|
||
document.getElementById('add-task-btn').addEventListener('click', () => showAddTaskModal());
|
||
document.getElementById('add-event-btn').addEventListener('click', () => showAddEventModal());
|
||
|
||
document.querySelector('.close').addEventListener('click', closeModal);
|
||
window.addEventListener('click', (e) => {
|
||
const modal = document.getElementById('modal');
|
||
if (e.target === modal) {
|
||
closeModal();
|
||
}
|
||
});
|
||
|
||
// Клик по дню для добавления
|
||
document.addEventListener('click', (e) => {
|
||
if (e.target.closest('.day-items')) {
|
||
const date = e.target.closest('.day-items').dataset.date;
|
||
if (e.ctrlKey || e.metaKey) {
|
||
showAddEventModal(date);
|
||
} else if (e.shiftKey) {
|
||
showAddTaskModal(date);
|
||
}
|
||
}
|
||
});
|
||
});
|
||
|