Улучшен календарный фильтр дат: динамическое количество дней, отображение месяца и сохранение позиции при выборе
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Календарная лента с 19 днями для фильтрации заказов
|
||||
* Сегодня в центре, навигация стрелками
|
||||
* Календарная лента с динамическим количеством дней для фильтрации заказов
|
||||
* Сегодня всегда в центре при загрузке, количество дней зависит от ширины экрана
|
||||
*/
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
@@ -16,6 +16,13 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
// Инициализация с сегодняшней датой в центре
|
||||
const carousel = new DateCarousel(container, minInputId, maxInputId);
|
||||
carousel.init();
|
||||
|
||||
// Пересчёт количества дней при изменении размера окна
|
||||
let resizeTimeout;
|
||||
window.addEventListener('resize', () => {
|
||||
clearTimeout(resizeTimeout);
|
||||
resizeTimeout = setTimeout(() => carousel.handleResize(), 250);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -32,18 +39,76 @@ class DateCarousel {
|
||||
this.centerDate = new Date(); // Центральная дата (по умолчанию сегодня)
|
||||
this.today = new Date();
|
||||
this.today.setHours(0, 0, 0, 0);
|
||||
this.daysCount = 0; // Будет рассчитано динамически
|
||||
}
|
||||
|
||||
/**
|
||||
* Инициализация календарной ленты
|
||||
*/
|
||||
init() {
|
||||
this.calculateDaysCount();
|
||||
this.loadSelectedDate(); // Загрузить выбранную дату из фильтра
|
||||
this.render();
|
||||
this.attachNavHandlers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Генерация и отображение 19 дней
|
||||
* Загрузка выбранной даты из скрытых полей фильтра
|
||||
*/
|
||||
loadSelectedDate() {
|
||||
// Если есть выбранная дата в фильтре, не центрируем на ней - пусть остается в том же положении
|
||||
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);
|
||||
|
||||
// Не изменяем центральную дату, просто оставим как есть
|
||||
console.log(`Selected date: ${this.formatDate(selectedDate)}, not centering`);
|
||||
}
|
||||
} else {
|
||||
// Если фильтра нет, центрируем на сегодняшнем дне
|
||||
console.log('No filter active - centering on today');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Расчёт количества дней на основе доступной ширины
|
||||
*/
|
||||
calculateDaysCount() {
|
||||
const containerWidth = this.container.offsetWidth;
|
||||
const dayButtonWidth = 78; // 70px min-width + 8px gap
|
||||
const maxDays = Math.floor(containerWidth / dayButtonWidth);
|
||||
|
||||
// Гарантируем нечётное количество дней для центрирования
|
||||
this.daysCount = maxDays % 2 === 0 ? maxDays - 1 : maxDays;
|
||||
|
||||
// Минимум 5 дней, максимум 31 день
|
||||
this.daysCount = Math.max(5, Math.min(31, this.daysCount));
|
||||
|
||||
console.log(`Calculated days count: ${this.daysCount} (container width: ${containerWidth}px)`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка изменения размера окна
|
||||
*/
|
||||
handleResize() {
|
||||
const oldDaysCount = this.daysCount;
|
||||
this.calculateDaysCount();
|
||||
|
||||
// Перерисовываем только если количество дней изменилось
|
||||
if (oldDaysCount !== this.daysCount) {
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Генерация и отображение дней
|
||||
*/
|
||||
render() {
|
||||
this.container.innerHTML = '';
|
||||
@@ -56,19 +121,20 @@ class DateCarousel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Генерация массива из 19 дней (±9 от центральной даты)
|
||||
* Генерация массива дней (динамическое количество от центральной даты)
|
||||
*/
|
||||
generateDays() {
|
||||
const days = [];
|
||||
const halfDays = Math.floor(this.daysCount / 2);
|
||||
|
||||
for (let i = -9; i <= 9; i++) {
|
||||
for (let i = -halfDays; i <= halfDays; i++) {
|
||||
const date = new Date(this.centerDate);
|
||||
date.setDate(date.getDate() + i);
|
||||
date.setHours(0, 0, 0, 0);
|
||||
|
||||
days.push({
|
||||
date: date,
|
||||
label: this.getDateLabel(date, i),
|
||||
label: this.getDateLabel(date),
|
||||
isToday: date.getTime() === this.today.getTime(),
|
||||
isCenter: i === 0
|
||||
});
|
||||
@@ -80,7 +146,7 @@ class DateCarousel {
|
||||
/**
|
||||
* Определение текстовой метки для даты
|
||||
*/
|
||||
getDateLabel(date, offset) {
|
||||
getDateLabel(date) {
|
||||
const yesterday = new Date(this.today);
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
yesterday.setHours(0, 0, 0, 0);
|
||||
@@ -125,9 +191,14 @@ class DateCarousel {
|
||||
weekday.className = 'date-btn-weekday';
|
||||
weekday.textContent = this.getWeekdayShort(dayData.date);
|
||||
|
||||
const month = document.createElement('div');
|
||||
month.className = 'date-btn-month';
|
||||
month.textContent = this.getMonthShort(dayData.date);
|
||||
|
||||
btn.appendChild(label);
|
||||
btn.appendChild(day);
|
||||
btn.appendChild(weekday);
|
||||
btn.appendChild(month);
|
||||
|
||||
// Обработчик клика
|
||||
btn.addEventListener('click', () => this.selectDate(dayData.date, btn));
|
||||
@@ -139,8 +210,18 @@ class DateCarousel {
|
||||
* Получить короткое название дня недели (ПН, ВТ, СР, ЧТ, ПТ, СБ, ВС)
|
||||
*/
|
||||
getWeekdayShort(date) {
|
||||
const weekdays = ['ВС', 'ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ'];
|
||||
return weekdays[date.getDay()];
|
||||
const weekdays = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС'];
|
||||
const dayIndex = date.getDay();
|
||||
// Сдвигаем индекс, чтобы понедельник был первым (0), а воскресенье - последним (6)
|
||||
return weekdays[(dayIndex + 6) % 7];
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить короткое название месяца (янв, фев, мар и т.д.)
|
||||
*/
|
||||
getMonthShort(date) {
|
||||
const months = ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'];
|
||||
return months[date.getMonth()];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user