/** * Date Filter Component * Provides a reusable date filtering UI using seasons data */ class DateFilter { constructor(containerId, options = {}) { this.container = document.getElementById(containerId); if (!this.container) { console.error(`[Date Filter] Container #${containerId} not found`); return; } this.options = { onFilterChange: options.onFilterChange || (() => {}), includeCustomRange: options.includeCustomRange !== false, includeCumulative: options.includeCumulative !== false, defaultFilter: options.defaultFilter || 'all-time', ...options }; this.seasonsFilter = window.seasonsFilter; this.currentFilter = { type: 'all-time', // 'all-time', 'season', 'week', 'custom', 'cumulative' startDate: null, endDate: null, season: null, week: null }; this.init(); } t(key, params = {}) { let value = (window.__t && window.__t(key)) || key; Object.entries(params).forEach(([name, replacement]) => { value = value.replace(`{${name}}`, replacement); }); return value; } async init() { // Load seasons data await this.seasonsFilter.loadSeasons(); // Render the UI this.render(); // Apply default filter if (this.options.defaultFilter !== 'all-time') { this.applyPresetFilter(this.options.defaultFilter); } } render() { const html = `
${this.options.includeCumulative ? ` ` : ''} ${this.options.includeCustomRange ? ` ` : ''}
`; this.container.innerHTML = html; this.attachEventListeners(); this.populateSelectors(); } attachEventListeners() { // Filter type buttons const filterButtons = this.container.querySelectorAll('[data-filter-type]'); filterButtons.forEach(btn => { btn.addEventListener('click', (e) => { const filterType = e.currentTarget.dataset.filterType; this.showFilterSection(filterType); }); }); // Season selection const seasonSelect = this.container.querySelector('#season-select'); if (seasonSelect) { seasonSelect.addEventListener('change', (e) => { const weekSelect = this.container.querySelector('#week-select'); if (e.target.value) { this.seasonsFilter.populateWeekSelect(weekSelect, e.target.value, true); weekSelect.disabled = false; } else { weekSelect.disabled = true; weekSelect.innerHTML = ``; } }); } // Cumulative season selection const cumulativeSeasonSelect = this.container.querySelector('#cumulative-season-select'); if (cumulativeSeasonSelect) { cumulativeSeasonSelect.addEventListener('change', (e) => { const weekSelect = this.container.querySelector('#cumulative-week-select'); if (e.target.value) { this.seasonsFilter.populateWeekSelect(weekSelect, e.target.value, false); weekSelect.disabled = false; } else { weekSelect.disabled = true; weekSelect.innerHTML = ``; } }); } // Apply buttons const applySeasonBtn = this.container.querySelector('#apply-season-filter'); if (applySeasonBtn) { applySeasonBtn.addEventListener('click', () => this.applySeasonFilter()); } const applyCumulativeBtn = this.container.querySelector('#apply-cumulative-filter'); if (applyCumulativeBtn) { applyCumulativeBtn.addEventListener('click', () => this.applyCumulativeFilter()); } const applyCustomBtn = this.container.querySelector('#apply-custom-filter'); if (applyCustomBtn) { applyCustomBtn.addEventListener('click', () => this.applyCustomFilter()); } // Clear filter const clearBtn = this.container.querySelector('#clear-filter'); if (clearBtn) { clearBtn.addEventListener('click', () => this.clearFilter()); } } populateSelectors() { const seasonSelect = this.container.querySelector('#season-select'); const cumulativeSeasonSelect = this.container.querySelector('#cumulative-season-select'); if (seasonSelect) { this.seasonsFilter.populateSeasonSelect(seasonSelect, false); } if (cumulativeSeasonSelect) { this.seasonsFilter.populateSeasonSelect(cumulativeSeasonSelect, false); } } showFilterSection(filterType) { // Update button states const buttons = this.container.querySelectorAll('[data-filter-type]'); buttons.forEach(btn => { if (btn.dataset.filterType === filterType) { btn.classList.add('filter-button-active'); btn.classList.remove('filter-button'); } else { btn.classList.remove('filter-button-active'); btn.classList.add('filter-button'); } }); // Hide all sections this.container.querySelector('#season-selector')?.classList.add('hidden'); this.container.querySelector('#cumulative-selector')?.classList.add('hidden'); this.container.querySelector('#custom-range-selector')?.classList.add('hidden'); // Show appropriate section switch (filterType) { case 'all-time': this.applyAllTimeFilter(); break; case 'current-season': this.applyCurrentSeasonFilter(); break; case 'season': this.container.querySelector('#season-selector')?.classList.remove('hidden'); break; case 'cumulative': this.container.querySelector('#cumulative-selector')?.classList.remove('hidden'); break; case 'custom': this.container.querySelector('#custom-range-selector')?.classList.remove('hidden'); break; } } applyAllTimeFilter() { this.currentFilter = { type: 'all-time', startDate: null, endDate: null, season: null, week: null }; this.updateFilterDisplay(this.t('dateFilter.allTimeStatistics')); this.options.onFilterChange(this.currentFilter); } applyCurrentSeasonFilter() { const currentSeasonInfo = this.seasonsFilter.getCurrentSeason(); if (!currentSeasonInfo) { console.error('[Date Filter] No current season found'); return; } const dateRange = this.seasonsFilter.getSeasonDateRange(currentSeasonInfo.name); if (!dateRange) return; this.currentFilter = { type: 'season', startDate: dateRange.startDate, endDate: dateRange.endDate, season: currentSeasonInfo.name, week: null }; this.updateFilterDisplay(this.t('dateFilter.currentSeasonValue', { season: currentSeasonInfo.name })); this.options.onFilterChange(this.currentFilter); } applySeasonFilter() { const seasonSelect = this.container.querySelector('#season-select'); const weekSelect = this.container.querySelector('#week-select'); const seasonName = seasonSelect.value; if (!seasonName) { alert(this.t('dateFilter.alertSelectSeason')); return; } const weekValue = weekSelect.value; let dateRange; let description; if (weekValue === 'all') { // Entire season dateRange = this.seasonsFilter.getSeasonDateRange(seasonName); description = this.t('dateFilter.seasonValue', { season: seasonName }); this.currentFilter = { type: 'season', startDate: dateRange.startDate, endDate: dateRange.endDate, season: seasonName, week: null }; } else { // Specific week const weekNumber = weekValue === 'final' ? null : parseInt(weekValue); dateRange = this.seasonsFilter.getWeekDateRange(seasonName, weekNumber); const season = this.seasonsFilter.getSeason(seasonName); const week = season.weeks.find(w => (w.weekNumber === weekNumber) || (weekValue === 'final' && w.weekNumber === null) ); description = `${seasonName} - ${week.displayName}`; this.currentFilter = { type: 'week', startDate: dateRange.startDate, endDate: dateRange.endDate, season: seasonName, week: weekNumber }; } this.updateFilterDisplay(description); this.options.onFilterChange(this.currentFilter); } applyCumulativeFilter() { const seasonSelect = this.container.querySelector('#cumulative-season-select'); const weekSelect = this.container.querySelector('#cumulative-week-select'); const seasonName = seasonSelect.value; const weekValue = weekSelect.value; if (!seasonName || !weekValue) { alert(this.t('dateFilter.alertSelectSeasonWeek')); return; } const weekNumber = weekValue === 'final' ? null : parseInt(weekValue); const dateRange = this.seasonsFilter.getWeekDateRange(seasonName, weekNumber); if (!dateRange) return; const season = this.seasonsFilter.getSeason(seasonName); const week = season.weeks.find(w => (w.weekNumber === weekNumber) || (weekValue === 'final' && w.weekNumber === null) ); this.currentFilter = { type: 'cumulative', startDate: null, // No start date for cumulative endDate: dateRange.endDate, season: seasonName, week: weekNumber }; this.updateFilterDisplay(this.t('dateFilter.cumulativeValue', { season: seasonName, week: week.displayName })); this.options.onFilterChange(this.currentFilter); } applyCustomFilter() { const startDateInput = this.container.querySelector('#start-date'); const endDateInput = this.container.querySelector('#end-date'); const startDate = startDateInput.value ? new Date(startDateInput.value) : null; const endDate = endDateInput.value ? new Date(endDateInput.value) : null; if (!startDate && !endDate) { alert(this.t('dateFilter.alertSelectDate')); return; } if (startDate && endDate && startDate > endDate) { alert(this.t('dateFilter.alertStartBeforeEnd')); return; } this.currentFilter = { type: 'custom', startDate: startDate, endDate: endDate, season: null, week: null }; let description = this.t('dateFilter.customRangePrefix') + ' '; if (startDate && endDate) { description += `${startDate.toLocaleDateString()} - ${endDate.toLocaleDateString()}`; } else if (startDate) { description += this.t('dateFilter.fromDate', { date: startDate.toLocaleDateString() }); } else { description += this.t('dateFilter.upToDate', { date: endDate.toLocaleDateString() }); } this.updateFilterDisplay(description); this.options.onFilterChange(this.currentFilter); } clearFilter() { this.applyAllTimeFilter(); } updateFilterDisplay(description) { const filterDisplay = this.container.querySelector('#current-filter-display'); const filterDescription = this.container.querySelector('#filter-description'); if (this.currentFilter.type === 'all-time') { filterDisplay?.classList.add('hidden'); } else { filterDisplay?.classList.remove('hidden'); if (filterDescription) { filterDescription.textContent = description; } } } applyPresetFilter(preset) { // Apply a preset filter (e.g., 'current-season', 'all-time') this.showFilterSection(preset); } getCurrentFilter() { return this.currentFilter; } getAPIQueryParams() { // Generate query parameters for API requests const params = new URLSearchParams(); if (this.currentFilter.type === 'all-time') { // No params needed for all-time return ''; } if (this.currentFilter.startDate) { const startDateISO = this.currentFilter.startDate.toISOString(); params.append('start_date', startDateISO); console.log('[Date Filter] Start Date:', this.currentFilter.startDate, '→', startDateISO); } if (this.currentFilter.endDate) { const endDate = new Date(this.currentFilter.endDate); endDate.setHours(23, 59, 59, 999); const endDateISO = endDate.toISOString(); params.append('end_date', endDateISO); console.log('[Date Filter] End Date:', endDate, '→', endDateISO); } if (this.currentFilter.season) { params.append('season', this.currentFilter.season); } if (this.currentFilter.week !== null) { params.append('week', this.currentFilter.week); } const queryString = params.toString() ? '?' + params.toString() : ''; console.log('[Date Filter] API Query Params:', queryString); return queryString; } } // Export for use in other scripts window.DateFilter = DateFilter;