import { DataLoader } from './data-loader.js'; import { StatsCalculator } from './stats-calculator.js'; import { SlideGenerator } from './slide-generator.js'; import { Slide } from './types.js'; class GitHubWrapped { private dataLoader: DataLoader; private statsCalculator?: StatsCalculator; private slideGenerator: SlideGenerator; private currentSlide = 0; private slides: Slide[] = []; private selectedAuthor?: string; constructor() { this.dataLoader = new DataLoader(); this.slideGenerator = new SlideGenerator(); } async init(): Promise { try { const data = await this.dataLoader.load(); this.statsCalculator = new StatsCalculator(data); this.showAuthorSelection(); } catch (error) { this.showError('Échec du chargement des données. Vérifiez que data.json existe.'); } } private showAuthorSelection(): void { const authors = this.dataLoader.getAuthors(); const container = document.getElementById('app')!; container.innerHTML = `

Git Wrapped 2025

Choisissez Votre Dev

${authors.map(author => { const stats = this.statsCalculator!.getAuthorStats(author); return ` `; }).join('')}
`; // Add click handlers document.querySelectorAll('.author-card').forEach(card => { card.addEventListener('click', (e) => { const author = (e.currentTarget as HTMLElement).dataset.author!; this.showAuthorStats(author); }); }); } private showAuthorStats(author: string): void { this.selectedAuthor = author; const stats = this.statsCalculator!.getAuthorStats(author); this.slides = this.slideGenerator.generateAuthorSlides(stats); this.currentSlide = 0; this.renderSlides(); this.setupNavigation(); } private renderSlides(): void { const container = document.getElementById('app')!; container.innerHTML = `
${this.slides.map((slide, i) => `
${slide.emoji ? `
${slide.emoji}
` : ''}

${slide.title}

${slide.subtitle ? `

${slide.subtitle}

` : ''}
${slide.content}
`).join('')}
`; this.updateSlide(); } private updateSlide(): void { // Update active slide document.querySelectorAll('.slide').forEach((slide, i) => { slide.classList.remove('active', 'prev'); if (i === this.currentSlide) { slide.classList.add('active'); } else if (i < this.currentSlide) { slide.classList.add('prev'); } }); // Update progress bar const progressFill = document.querySelector('.progress-fill') as HTMLElement; if (progressFill) { progressFill.style.width = `${((this.currentSlide + 1) / this.slides.length) * 100}%`; } // Update button states const prevBtn = document.getElementById('prevBtn') as HTMLButtonElement; const nextBtn = document.getElementById('nextBtn') as HTMLButtonElement; if (prevBtn) prevBtn.style.opacity = this.currentSlide === 0 ? '0.3' : '1'; if (nextBtn) nextBtn.style.opacity = this.currentSlide === this.slides.length - 1 ? '0.3' : '1'; } private setupNavigation(): void { document.getElementById('backBtn')?.addEventListener('click', () => { this.showAuthorSelection(); }); document.getElementById('prevBtn')?.addEventListener('click', () => { if (this.currentSlide > 0) { this.currentSlide--; this.updateSlide(); } }); document.getElementById('nextBtn')?.addEventListener('click', () => { if (this.currentSlide < this.slides.length - 1) { this.currentSlide++; this.updateSlide(); } }); // Keyboard navigation document.addEventListener('keydown', (e) => { if (e.key === 'ArrowLeft' && this.currentSlide > 0) { this.currentSlide--; this.updateSlide(); } else if (e.key === 'ArrowRight' && this.currentSlide < this.slides.length - 1) { this.currentSlide++; this.updateSlide(); } else if (e.key === 'Escape' && this.selectedAuthor) { this.showAuthorSelection(); } }); } private showError(message: string): void { const container = document.getElementById('app')!; container.innerHTML = `

Erreur

${message}

`; } } // Initialize the app const app = new GitHubWrapped(); app.init();