const API_BASE_URL = window.location.origin; document.addEventListener('DOMContentLoaded', () => { // Инициализация табов const tabButtons = document.querySelectorAll('.tab-button'); console.log('Найдено табов:', tabButtons.length); tabButtons.forEach(button => { button.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); const tabName = button.getAttribute('data-tab'); console.log('Клик на таб:', tabName); switchTab(tabName); }); }); // Traditional summary form const form = document.getElementById('summaryForm'); const periodSelect = document.getElementById('period'); const customDatesDiv = document.getElementById('customDates'); const loadingDiv = document.getElementById('loading'); const errorDiv = document.getElementById('error'); const resultsDiv = document.getElementById('results'); // AI summary form const aiForm = document.getElementById('aiSummaryForm'); const aiPeriodSelect = document.getElementById('aiPeriod'); const aiCustomDatesDiv = document.getElementById('aiCustomDates'); // Показываем/скрываем поля для произвольного периода (Traditional) periodSelect.addEventListener('change', (e) => { if (e.target.value === 'custom') { customDatesDiv.style.display = 'grid'; } else { customDatesDiv.style.display = 'none'; } }); // Показываем/скрываем поля для произвольного периода (AI) aiPeriodSelect.addEventListener('change', (e) => { if (e.target.value === 'custom') { aiCustomDatesDiv.style.display = 'grid'; } else { aiCustomDatesDiv.style.display = 'none'; } }); // Traditional summary submit form.addEventListener('submit', async (e) => { e.preventDefault(); errorDiv.style.display = 'none'; resultsDiv.style.display = 'none'; loadingDiv.style.display = 'block'; try { const repositoryPath = document.getElementById('repositoryPath').value || '.'; const period = document.getElementById('period').value; const startDate = document.getElementById('startDate').value; const endDate = document.getElementById('endDate').value; const requestBody = { repositoryPath: repositoryPath || undefined }; if (period === 'custom') { if (startDate) requestBody.startDate = startDate; if (endDate) requestBody.endDate = endDate; } else if (period) { requestBody.period = period; } const response = await fetch(`${API_BASE_URL}/api/summary`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestBody) }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.error || `Ошибка: ${response.statusText}`); } const data = await response.json(); displayResults(data, false); } catch (error) { showError(error.message); } finally { loadingDiv.style.display = 'none'; } }); // AI summary submit aiForm.addEventListener('submit', async (e) => { e.preventDefault(); errorDiv.style.display = 'none'; resultsDiv.style.display = 'none'; loadingDiv.style.display = 'block'; try { const repositoryPath = document.getElementById('aiRepositoryPath').value || '.'; const period = document.getElementById('aiPeriod').value; const startDate = document.getElementById('aiStartDate').value; const endDate = document.getElementById('aiEndDate').value; const requestBody = { repositoryPath: repositoryPath || undefined }; if (period === 'custom') { if (startDate) requestBody.startDate = startDate; if (endDate) requestBody.endDate = endDate; } else if (period) { requestBody.period = period; } const response = await fetch(`${API_BASE_URL}/api/summary/ai`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestBody) }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.error || `Ошибка: ${response.statusText}`); } const data = await response.json(); displayResults(data, true); } catch (error) { showError(error.message); } finally { loadingDiv.style.display = 'none'; } }); }); function switchTab(tabName) { console.log('switchTab вызвана с:', tabName); // Скрыть все tab-content const tabContents = document.querySelectorAll('.tab-content'); console.log('Найдено контентов:', tabContents.length); tabContents.forEach(content => { content.classList.remove('active'); console.log('Скрыт:', content.getAttribute('data-tab')); }); // Убрать active класс со всех кнопок const tabButtons = document.querySelectorAll('.tab-button'); console.log('Найдено кнопок:', tabButtons.length); tabButtons.forEach(button => button.classList.remove('active')); // Показать выбранный tab const selectedContent = document.querySelector(`.tab-content[data-tab="${tabName}"]`); console.log('Выбранный контент:', selectedContent); if (selectedContent) { selectedContent.classList.add('active'); console.log('Активирован контент для:', tabName); } // Выделить выбранную кнопку const selectedButton = document.querySelector(`.tab-button[data-tab="${tabName}"]`); console.log('Выбранная кнопка:', selectedButton); if (selectedButton) { selectedButton.classList.add('active'); console.log('Активирована кнопка для:', tabName); } } function showError(message) { const errorDiv = document.getElementById('error'); errorDiv.textContent = `Ошибка: ${message}`; errorDiv.style.display = 'block'; } function displayResults(data, isAiSummary) { const resultsDiv = document.getElementById('results'); const aiSummaryResult = document.getElementById('aiSummaryResult'); resultsDiv.style.display = 'block'; // Если это AI саммари, показываем его if (isAiSummary) { aiSummaryResult.style.display = 'block'; document.getElementById('aiSummaryText').innerHTML = escapeHtml(data.summary || ''); document.getElementById('aiCommitsCount').textContent = data.commitsCount || 0; } else { aiSummaryResult.style.display = 'none'; } // Период const periodInfo = document.getElementById('periodInfo'); periodInfo.textContent = data.periodInfo?.description || data.period?.description || 'Период не указан'; // Статистика (для traditional summary) if (!isAiSummary && data.stats) { const stats = data.stats; document.getElementById('totalCommits').textContent = formatNumber(stats.totalCommits || 0); document.getElementById('totalFiles').textContent = formatNumber(stats.totalFilesChanged || 0); document.getElementById('totalAdditions').textContent = formatNumber(stats.totalAdditions || 0); document.getElementById('totalDeletions').textContent = formatNumber(stats.totalDeletions || 0); document.getElementById('uniqueContributors').textContent = formatNumber(stats.uniqueContributors || 0); // Категории const categoriesDiv = document.getElementById('categories'); categoriesDiv.innerHTML = ''; if (data.categories && data.categories.length > 0) { data.categories.forEach(category => { const categoryCard = document.createElement('div'); categoryCard.className = 'category-card'; categoryCard.innerHTML = `
Категории не найдены
'; } // Топ коммиты const topCommitsDiv = document.getElementById('topCommits'); topCommitsDiv.innerHTML = ''; if (data.topCommits && data.topCommits.length > 0) { data.topCommits.forEach(commit => { const commitCard = document.createElement('div'); commitCard.className = 'commit-item'; const commitDate = new Date(commit.when).toLocaleDateString('ru-RU', { year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' }); commitCard.innerHTML = `Коммиты не найдены
'; } } else if (isAiSummary) { // Для AI саммари скрываем статистику document.querySelector('.stats-grid').style.display = 'none'; document.querySelector('.categories-section').style.display = 'none'; document.querySelector('.top-commits-section').style.display = 'none'; resultsDiv.scrollIntoView({ behavior: 'smooth', block: 'start' }); } function formatNumber(num) { return new Intl.NumberFormat('ru-RU').format(num); } function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } }