Fix date carousel position persistence to keep selected date in place
- Selected date now stays at its clicked position instead of jumping to center - Fixed timezone issue in localStorage causing dates to shift by one day - Carousel position is preserved across page reloads - Simplified date selection logic by removing complex offset calculations - Added updateSelectedState() method to update selection without re-rendering 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -43,38 +43,11 @@ class DateCarousel {
|
|||||||
// Загружаем сохранённую дату из localStorage или устанавливаем сегодня
|
// Загружаем сохранённую дату из localStorage или устанавливаем сегодня
|
||||||
const savedData = this.loadSavedCenterDate();
|
const savedData = this.loadSavedCenterDate();
|
||||||
if (savedData) {
|
if (savedData) {
|
||||||
// Если есть смещение, это означает, что дата была выбрана пользователем
|
// Восстанавливаем центральную дату как есть
|
||||||
if (savedData.offset !== 0) {
|
|
||||||
// Проверяем, есть ли выбранная дата в фильтрах
|
|
||||||
if (this.minInput && this.minInput.value && this.maxInput.value &&
|
|
||||||
this.minInput.value === this.maxInput.value) {
|
|
||||||
// Получаем выбранную дату из фильтра
|
|
||||||
const parts = this.minInput.value.split('-');
|
|
||||||
if (parts.length === 3) {
|
|
||||||
const selectedDate = new Date(
|
|
||||||
parseInt(parts[0]),
|
|
||||||
parseInt(parts[1]) - 1,
|
|
||||||
parseInt(parts[2])
|
|
||||||
);
|
|
||||||
selectedDate.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
// Вычисляем центральную дату: выбранная дата минус смещение
|
|
||||||
this.centerDate = new Date(selectedDate);
|
|
||||||
this.centerDate.setDate(this.centerDate.getDate() - savedData.offset);
|
|
||||||
} else {
|
|
||||||
// Если дата в фильтре некорректна, используем сохранённую центральную дату
|
|
||||||
this.centerDate = savedData.centerDate;
|
this.centerDate = savedData.centerDate;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Если нет фильтра с одной датой, используем сохранённую центральную дату
|
|
||||||
this.centerDate = savedData.centerDate;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Если смещения нет, используем сохранённую центральную дату
|
|
||||||
this.centerDate = savedData.centerDate;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this.centerDate = new Date();
|
this.centerDate = new Date();
|
||||||
|
this.centerDate.setHours(0, 0, 0, 0); // Сбрасываем время!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,43 +58,6 @@ class DateCarousel {
|
|||||||
this.calculateDaysCount();
|
this.calculateDaysCount();
|
||||||
this.loadSelectedDate(); // Загрузить выбранную дату из фильтра
|
this.loadSelectedDate(); // Загрузить выбранную дату из фильтра
|
||||||
|
|
||||||
// Если в localStorage есть сохраненные данные
|
|
||||||
const savedData = this.loadSavedCenterDate();
|
|
||||||
if (savedData) {
|
|
||||||
// Если есть смещение, это означает, что дата была выбрана пользователем
|
|
||||||
if (savedData.offset !== 0) {
|
|
||||||
// Проверяем, есть ли выбранная дата в фильтрах
|
|
||||||
if (this.minInput.value && this.maxInput.value &&
|
|
||||||
this.minInput.value === this.maxInput.value) {
|
|
||||||
// Получаем выбранную дату из фильтра
|
|
||||||
const parts = this.minInput.value.split('-');
|
|
||||||
if (parts.length === 3) {
|
|
||||||
const selectedDate = new Date(
|
|
||||||
parseInt(parts[0]),
|
|
||||||
parseInt(parts[1]) - 1,
|
|
||||||
parseInt(parts[2])
|
|
||||||
);
|
|
||||||
selectedDate.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
// Вычисляем центральную дату: выбранная дата минус смещение
|
|
||||||
// (т.к. смещение показывает, на сколько дней выбранная дата
|
|
||||||
// смещена вправо от центра)
|
|
||||||
this.centerDate = new Date(selectedDate);
|
|
||||||
this.centerDate.setDate(this.centerDate.getDate() - savedData.offset);
|
|
||||||
} else {
|
|
||||||
// Если дата в фильтре некорректна, используем сохранённую центральную дату
|
|
||||||
this.centerDate = savedData.centerDate;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Если нет фильтра с одной датой, используем сохранённую центральную дату
|
|
||||||
this.centerDate = savedData.centerDate;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Если смещения нет, используем сохранённую центральную дату
|
|
||||||
this.centerDate = savedData.centerDate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.render();
|
this.render();
|
||||||
this.attachNavHandlers();
|
this.attachNavHandlers();
|
||||||
this.attachTodayHandler();
|
this.attachTodayHandler();
|
||||||
@@ -131,33 +67,13 @@ class DateCarousel {
|
|||||||
* Загрузка выбранной даты из скрытых полей фильтра
|
* Загрузка выбранной даты из скрытых полей фильтра
|
||||||
*/
|
*/
|
||||||
loadSelectedDate() {
|
loadSelectedDate() {
|
||||||
// Если есть выбранная дата в фильтре
|
// Просто логируем выбранную дату, но НЕ меняем centerDate
|
||||||
|
// Карусель остается там, где была (centerDate из localStorage или today)
|
||||||
if (this.minInput.value && this.maxInput.value &&
|
if (this.minInput.value && this.maxInput.value &&
|
||||||
this.minInput.value === this.maxInput.value) {
|
this.minInput.value === this.maxInput.value) {
|
||||||
const parts = this.minInput.value.split('-');
|
console.log(`Selected date in filter: ${this.minInput.value}, but keeping current center`);
|
||||||
if (parts.length === 3) {
|
|
||||||
const selectedDate = new Date(
|
|
||||||
parseInt(parts[0]),
|
|
||||||
parseInt(parts[1]) - 1,
|
|
||||||
parseInt(parts[2])
|
|
||||||
);
|
|
||||||
selectedDate.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
// Устанавливаем центральную дату на выбранную дату только если фильтр отличается от сегодняшней даты
|
|
||||||
// Это позволяет определить, был ли фильтр установлен до посещения страницы
|
|
||||||
const todayFormatted = this.formatDate(this.today);
|
|
||||||
if (this.minInput.value !== todayFormatted) {
|
|
||||||
// Возможно, фильтр уже был установлен, но мы всё равно не хотим центрировать
|
|
||||||
// для согласованности с поведением после выбора даты
|
|
||||||
console.log(`Selected date in filter: ${this.formatDate(selectedDate)}, keeping current view`);
|
|
||||||
} else {
|
} else {
|
||||||
// Если фильтр равен сегодняшней дате, можно центрировать на сегодня
|
console.log('No filter active - keeping current center');
|
||||||
console.log(`Filter is today: ${this.formatDate(selectedDate)}, keeping current view`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Если фильтра нет, центрируем на сегодняшнем дне
|
|
||||||
console.log('No filter active - centering on today');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,6 +243,35 @@ class DateCarousel {
|
|||||||
return this.minInput.value === formattedDate && this.maxInput.value === formattedDate;
|
return this.minInput.value === formattedDate && this.maxInput.value === formattedDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Обновление состояния selected для всех кнопок без перерисовки
|
||||||
|
*/
|
||||||
|
updateSelectedState() {
|
||||||
|
const buttons = this.container.querySelectorAll('.date-btn');
|
||||||
|
buttons.forEach(btn => {
|
||||||
|
// Получаем дату из кнопки (день месяца)
|
||||||
|
const dayElement = btn.querySelector('.date-btn-day');
|
||||||
|
const monthElement = btn.querySelector('.date-btn-month');
|
||||||
|
if (dayElement && monthElement) {
|
||||||
|
const day = parseInt(dayElement.textContent);
|
||||||
|
const monthShort = monthElement.textContent;
|
||||||
|
|
||||||
|
// Находим дату кнопки, сравнивая с датами в generateDays
|
||||||
|
const days = this.generateDays();
|
||||||
|
const matchingDay = days.find(d =>
|
||||||
|
d.date.getDate() === day &&
|
||||||
|
this.getMonthShort(d.date) === monthShort
|
||||||
|
);
|
||||||
|
|
||||||
|
if (matchingDay && this.isDateSelected(matchingDay.date)) {
|
||||||
|
btn.classList.add('selected');
|
||||||
|
} else {
|
||||||
|
btn.classList.remove('selected');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Выбор даты (установка в оба поля фильтра)
|
* Выбор даты (установка в оба поля фильтра)
|
||||||
*/
|
*/
|
||||||
@@ -336,19 +281,21 @@ class DateCarousel {
|
|||||||
this.minInput.value = formattedDate;
|
this.minInput.value = formattedDate;
|
||||||
this.maxInput.value = formattedDate;
|
this.maxInput.value = formattedDate;
|
||||||
|
|
||||||
// Вычисляем смещение выбранной даты от центра
|
// НЕ меняем centerDate - оставляем карусель на месте
|
||||||
const offset = this.calculateDateOffset(date);
|
// Только обновляем визуальное выделение
|
||||||
// Сохраняем центральную дату и смещение перед отправкой формы
|
|
||||||
this.saveCenterDate(offset);
|
|
||||||
|
|
||||||
// Визуальная обратная связь
|
// Визуальная обратная связь
|
||||||
btn.classList.add('clicked');
|
btn.classList.add('clicked');
|
||||||
setTimeout(() => btn.classList.remove('clicked'), 300);
|
setTimeout(() => btn.classList.remove('clicked'), 300);
|
||||||
|
|
||||||
// Обновление визуального состояния (без изменения центральной даты)
|
// Обновление визуального состояния (только класс selected)
|
||||||
this.render();
|
this.updateSelectedState();
|
||||||
|
|
||||||
console.log(`Selected date: ${formattedDate}, offset: ${offset}`);
|
console.log(`Selected date: ${formattedDate}, center stays at: ${this.formatDate(this.centerDate)}`);
|
||||||
|
|
||||||
|
// ВАЖНО: Сохраняем текущую позицию карусели перед отправкой формы
|
||||||
|
// чтобы после перезагрузки страницы карусель осталась на том же месте
|
||||||
|
this.saveCenterDate();
|
||||||
|
|
||||||
// Автоматическая отправка формы
|
// Автоматическая отправка формы
|
||||||
const form = this.minInput.closest('form');
|
const form = this.minInput.closest('form');
|
||||||
@@ -443,7 +390,8 @@ class DateCarousel {
|
|||||||
*/
|
*/
|
||||||
saveCenterDate(offset = 0) {
|
saveCenterDate(offset = 0) {
|
||||||
const key = `date_carousel_center_${this.minInputId}`;
|
const key = `date_carousel_center_${this.minInputId}`;
|
||||||
const centerDateStr = this.centerDate.toISOString().split('T')[0]; // Формат YYYY-MM-DD
|
// Используем formatDate вместо toISOString для избежания проблем с часовыми поясами
|
||||||
|
const centerDateStr = this.formatDate(this.centerDate);
|
||||||
const saveData = {
|
const saveData = {
|
||||||
centerDate: centerDateStr,
|
centerDate: centerDateStr,
|
||||||
offset: offset
|
offset: offset
|
||||||
|
|||||||
Reference in New Issue
Block a user