diff --git a/src/app/@components/leaderboard/leaderboard.interface.ts b/src/app/@components/leaderboard/leaderboard.interface.ts index 3f811fb..4d10101 100644 --- a/src/app/@components/leaderboard/leaderboard.interface.ts +++ b/src/app/@components/leaderboard/leaderboard.interface.ts @@ -14,6 +14,7 @@ export interface TotalKiteData { rank: number; img_url: string; user_id: string; + id: string; }; stat: { all_time: { max_height: number; diff --git a/src/app/@components/leaderboard/leaderboard/leaderboard.component.html b/src/app/@components/leaderboard/leaderboard/leaderboard.component.html index 2dd1852..ace5780 100644 --- a/src/app/@components/leaderboard/leaderboard/leaderboard.component.html +++ b/src/app/@components/leaderboard/leaderboard/leaderboard.component.html @@ -7,15 +7,15 @@

Leaderboard

+ (click)="selectTopPlayer(topPlayers[1]);$event.stopPropagation()">
+ (click)="selectTopPlayer(bestPlayer);$event.stopPropagation()">
+ (click)="selectTopPlayer(topPlayers[2]);$event.stopPropagation()">
diff --git a/src/app/@components/leaderboard/leaderboard/leaderboard.component.ts b/src/app/@components/leaderboard/leaderboard/leaderboard.component.ts index f1311ce..c6bd8fa 100644 --- a/src/app/@components/leaderboard/leaderboard/leaderboard.component.ts +++ b/src/app/@components/leaderboard/leaderboard/leaderboard.component.ts @@ -4,6 +4,7 @@ import { Player } from '../leaderboard.interface'; import { KiteApiService } from '../../../pages/kite-competition/kite/kite-api.service'; import { SharedDataService } from '../../../services/shared-data.service'; import { PlayersComponent } from '../players/players.component'; +import { LoaderService } from '../../../@theme/components/loader/loader.service'; @Component({ @@ -19,17 +20,19 @@ export class KiteLeaderboardComponent implements OnInit { remainingPlayers: Player[] = []; combinedPlayers: Player[] = []; // Combined list of top and remaining players - constructor(private router: Router, + constructor( + private router: Router, private kiteApiService: KiteApiService, private sharedDataService: SharedDataService, - - ) { } + private loaderService: LoaderService, + ) {} ngOnInit(): void { this.loadLeaderboard(); } loadLeaderboard() { + this.loaderService.show(); this.kiteApiService.getPlayersLeaderboard().subscribe( (data) => { // Sort players by kite height in descending order @@ -64,6 +67,9 @@ export class KiteLeaderboardComponent implements OnInit { }, (error) => { console.error('Error fetching leaderboard:', error); + }, + () => { + this.loaderService.hide(); } ); } @@ -71,25 +77,10 @@ export class KiteLeaderboardComponent implements OnInit { this.router.navigate(['/kite/player/all']); } - // selectTopPlayer(player: Player) { - // if (this.playersComponent) { - // this.playersComponent.clearHoverAndActiveState(); - // } - // this.router.navigate(['/kite/player', player.id], { - // state: { - // player, - // }, - // }); - // } - selectTopPlayer(player: Player) { if (this.playersComponent) { this.playersComponent.clearHoverAndActiveState(); } - - // Clear the activePlayerId from local storage - localStorage.removeItem('activePlayerId'); - this.router.navigate(['/kite/player', player.id], { state: { player, @@ -97,5 +88,21 @@ export class KiteLeaderboardComponent implements OnInit { }); } + // selectTopPlayer(player: Player) { + // if (this.playersComponent) { + // this.playersComponent.clearHoverAndActiveState(); + // } + + // // Clear the activePlayerId from local storage + // localStorage.removeItem('activePlayerId'); + + // this.router.navigate(['/kite/player', player.id], { + // state: { + // player, + // }, + // }); + // } + } + diff --git a/src/app/@components/leaderboard/my-records/my-records.component.ts b/src/app/@components/leaderboard/my-records/my-records.component.ts index 6d6b530..8a2cbfa 100644 --- a/src/app/@components/leaderboard/my-records/my-records.component.ts +++ b/src/app/@components/leaderboard/my-records/my-records.component.ts @@ -1,10 +1,11 @@ import { Component, OnInit, OnDestroy } from '@angular/core'; import { KiteApiService } from '../../../pages/kite-competition/kite/kite-api.service'; import { Router } from '@angular/router'; -import { KitePlayer } from '../leaderboard.interface'; +import { TotalKiteData } from '../leaderboard.interface'; import { OAuth2Service } from '../../../modules/oauth2/oauth2.service'; import { UserProfile } from '../../../common/interfaces/user.interface'; import { Subscription } from 'rxjs'; +import { LoaderService } from '../../../@theme/components/loader/loader.service'; @Component({ selector: 'ngx-myrecords', @@ -13,7 +14,7 @@ import { Subscription } from 'rxjs'; }) export class MyRecordsComponent implements OnInit, OnDestroy { - playerData: any; // Adjust to your specific type + playerData: TotalKiteData | null = null; errorMessage: string | null = null; userSubscription: Subscription | null = null; @@ -21,21 +22,19 @@ export class MyRecordsComponent implements OnInit, OnDestroy { private kiteApiService: KiteApiService, private router: Router, private oAuth2Service: OAuth2Service, + private loaderService: LoaderService ) {} ngOnInit(): void { // Subscribe to user changes this.userSubscription = this.oAuth2Service.getUser().subscribe(userProfile => { if (userProfile && userProfile._id) { - this.fetchUserData(userProfile._id); + this.checkLocalStorageAndFetchData(userProfile._id); } else { this.errorMessage = 'ඔයාගේ විස්තර බලන්න මුලින්ම Sign In වෙන්න'; this.playerData = null; } }); - - // Initial check in case the user is already logged in when the component is initialized - this.checkLocalStorageAndFetchData(); } private getUserIdFromLocalStorage(): string | null { @@ -47,16 +46,17 @@ export class MyRecordsComponent implements OnInit, OnDestroy { return null; } - checkLocalStorageAndFetchData(): void { - const userId = this.getUserIdFromLocalStorage(); - if (userId) { - this.fetchUserData(userId); + checkLocalStorageAndFetchData(userId?: string): void { + const storedUserId = userId || this.getUserIdFromLocalStorage(); + if (storedUserId) { + this.fetchUserData(storedUserId); } else { this.errorMessage = 'ඔයාගේ විස්තර බලන්න මුලින්ම Sign In වෙන්න'; } } fetchUserData(userId: string): void { + this.loaderService.show(); this.kiteApiService.getLatestUserData(userId).subscribe( (data) => { this.playerData = data; @@ -71,28 +71,19 @@ export class MyRecordsComponent implements OnInit, OnDestroy { console.error('Error fetching user data', error); this.errorMessage = 'සරුංගල් මේනියා සමඟ ලියාපදිංචි වී \ නෙළුම් කුළුණට වඩා උඩින් සරුංගල් යවන්න ඔයත් එකතු වෙන්න'; + }, + () => { + this.loaderService.hide(); } ); } onCardClick(): void { - const userId = this.getUserIdFromLocalStorage(); - if (userId) { - this.kiteApiService.getKitePlayerByUserId(userId).subscribe( - (playerData: KitePlayer) => { - if (playerData && playerData._id) { - const playerId = playerData._id; - this.router.navigate([`/kite/player/${playerId}`]); - } else { - console.log('No player ID found. Not navigating.'); - } - }, - (error) => { - console.error('Error fetching player data by user ID', error); - } - ); + if (this.playerData && this.playerData.player && this.playerData.player.id) { + const playerId = this.playerData.player.id; + this.router.navigate([`/kite/player/${playerId}`]); } else { - console.log('No user ID found in local storage. Not navigating.'); + console.log('Player data not found or player ID missing. Not navigating.'); } } @@ -103,3 +94,5 @@ export class MyRecordsComponent implements OnInit, OnDestroy { } } } + + diff --git a/src/app/@theme/components/loader/loader.component.html b/src/app/@theme/components/loader/loader.component.html index a11bc99..275858d 100644 --- a/src/app/@theme/components/loader/loader.component.html +++ b/src/app/@theme/components/loader/loader.component.html @@ -1,6 +1,5 @@ -
- - +
+
diff --git a/src/app/@theme/components/loader/loader.component.scss b/src/app/@theme/components/loader/loader.component.scss index 377151a..cc18253 100644 --- a/src/app/@theme/components/loader/loader.component.scss +++ b/src/app/@theme/components/loader/loader.component.scss @@ -1,17 +1,19 @@ .progress-loader{ + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; display: flex; justify-content: center; - position: fixed; - inset: 0; align-items: center; - z-index: 999; - background-color: rgba(0,0,0,0.3); + z-index: 1000; + } + + .loader-dark { + background-color: rgb(34, 43, 69); } -.mat-mdc-progress-spinner circle { - stroke: #665b7d; +.loader-light { + background-color:#bbdefb; } - - - - diff --git a/src/app/@theme/components/loader/loader.component.ts b/src/app/@theme/components/loader/loader.component.ts index a21604e..2c02152 100644 --- a/src/app/@theme/components/loader/loader.component.ts +++ b/src/app/@theme/components/loader/loader.component.ts @@ -1,6 +1,8 @@ import { Component, OnInit } from '@angular/core'; import { Subscription } from 'rxjs'; import { LoaderService, LoaderState } from './loader.service'; +import { Router, NavigationEnd } from '@angular/router'; +import { filter } from 'rxjs/operators'; @Component({ selector: 'ngx-loader', @@ -10,8 +12,17 @@ import { LoaderService, LoaderState } from './loader.service'; export class LoaderComponent implements OnInit { loading = false; private subscription: Subscription; + isDarkTheme: boolean = false; - constructor(loaderService: LoaderService) { + + private checkRoute(): void { + const currentRoute = this.router.url; + this.isDarkTheme = currentRoute.startsWith('/kite'); + } + + constructor(loaderService: LoaderService, + private router: Router, + ) { this.subscription = loaderService.loaderState .subscribe((state: LoaderState) => { this.loading = state.show; @@ -19,6 +30,12 @@ export class LoaderComponent implements OnInit { } ngOnInit(): void { + this.router.events.pipe( + filter(event => event instanceof NavigationEnd) + ).subscribe(() => { + this.checkRoute(); + }); + this.checkRoute(); } } diff --git a/src/app/@theme/components/loading-spinner/loading-spinner.component.html b/src/app/@theme/components/loading-spinner/loading-spinner.component.html deleted file mode 100644 index 83a40a4..0000000 --- a/src/app/@theme/components/loading-spinner/loading-spinner.component.html +++ /dev/null @@ -1,9 +0,0 @@ - - - -
- -
diff --git a/src/app/@theme/components/loading-spinner/loading-spinner.component.scss b/src/app/@theme/components/loading-spinner/loading-spinner.component.scss deleted file mode 100644 index c8e0f1f..0000000 --- a/src/app/@theme/components/loading-spinner/loading-spinner.component.scss +++ /dev/null @@ -1,22 +0,0 @@ -.loading-spinner-overlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - display: flex; - justify-content: center; - align-items: center; - z-index: 1000; - background-color: rgb(34, 43, 69); -} - - - - - - - - - - diff --git a/src/app/@theme/components/loading-spinner/loading-spinner.component.ts b/src/app/@theme/components/loading-spinner/loading-spinner.component.ts deleted file mode 100644 index d2b958d..0000000 --- a/src/app/@theme/components/loading-spinner/loading-spinner.component.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'ngx-loading-spinner', - templateUrl: './loading-spinner.component.html', - styleUrls: ['./loading-spinner.component.scss'], -}) -export class LoadingSpinnerComponent {} diff --git a/src/app/@theme/theme.module.ts b/src/app/@theme/theme.module.ts index 21c7ba0..80b9d52 100644 --- a/src/app/@theme/theme.module.ts +++ b/src/app/@theme/theme.module.ts @@ -37,7 +37,6 @@ import { FormsModule } from '@angular/forms'; import { ReactiveFormsModule } from '@angular/forms'; import { MatInputModule } from '@angular/material/input'; import { MatAutocompleteModule } from '@angular/material/autocomplete'; -import { LoadingSpinnerComponent } from './components/loading-spinner/loading-spinner.component'; const palette = { @@ -114,7 +113,6 @@ const COMPONENTS = [ WeatherPortalLayoutComponent, LoaderComponent, KiteSearchComponent, - LoadingSpinnerComponent, ]; const PIPES = [ CapitalizePipe, diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 68ff8fd..0d0cc75 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -3,34 +3,6 @@ // * Copyright Akveo. All Rights Reserved. // * Licensed under the MIT License. See License.txt in the project root for license information. // */ -// import { Component, OnInit } from '@angular/core'; -// import packageJson from '../../package.json'; -// import { AnalyticsService } from './@core/utils/analytics.service'; -// import { SeoService } from './@core/utils/seo.service'; - -// @Component({ -// selector: 'ngx-app', -// template: ` -// -// -// `, -// }) -// export class AppComponent implements OnInit { -// constructor( -// private analytics: AnalyticsService, -// private seoService: SeoService, -// ) {} - -// ngOnInit(): void { -// this.analytics.trackPageViews(); -// this.seoService.trackCanonicalChanges(); -// console.info(`v${packageJson.version}`); -// } - -// } - - - import { Component, OnInit, Renderer2 } from '@angular/core'; import packageJson from '../../package.json'; @@ -45,8 +17,7 @@ import { ThemeService } from './@core/services/theme.service'; selector: 'ngx-app', template: ` - - + `, styles: [` :host { @@ -70,39 +41,11 @@ export class AppComponent implements OnInit { this.seoService.trackCanonicalChanges(); console.info(`v${packageJson.version}`); - this.router.events.subscribe((event: RouterEvent) => { - if (event instanceof NavigationStart) { - this.showSpinner(); - } else if (event instanceof NavigationEnd) { - this.hideSpinnerWithDelay(); + this.router.events.subscribe(event => { + if (event instanceof NavigationEnd) { this.applyThemeBasedOnRoute(event.urlAfterRedirects); - } else if (event instanceof NavigationCancel || event instanceof NavigationError) { - this.hideSpinnerWithDelay(); } }); - - - // this.analytics.trackPageViews(); - // this.seoService.trackCanonicalChanges(); - // console.info(`v${packageJson.version}`); - - // this.router.events.subscribe(event => { - // if (event instanceof NavigationEnd) { - // this.applyThemeBasedOnRoute(event.urlAfterRedirects); - // } - // }); - } - - // Method to show the loading spinner - showSpinner(): void { - this.loading = true; - } - - // Method to hide the spinner with a slight delay (optional) - hideSpinnerWithDelay(delay: number = 1000): void { - setTimeout(() => { - this.loading = false; - }, delay); } diff --git a/src/app/pages/kite-competition/height-comparison/height-comparison.component.scss b/src/app/pages/kite-competition/height-comparison/height-comparison.component.scss index 93f8132..89f45e4 100644 --- a/src/app/pages/kite-competition/height-comparison/height-comparison.component.scss +++ b/src/app/pages/kite-competition/height-comparison/height-comparison.component.scss @@ -148,10 +148,6 @@ margin-right: -80px; transition: height 2s ease-in-out; } -.mountword{ - color:orange ; -} - .kite-image { width: 50px; height: 40px; diff --git a/src/app/pages/kite-competition/kite-dashboard/kite-dashboard.component.ts b/src/app/pages/kite-competition/kite-dashboard/kite-dashboard.component.ts index f9016dc..e844037 100644 --- a/src/app/pages/kite-competition/kite-dashboard/kite-dashboard.component.ts +++ b/src/app/pages/kite-competition/kite-dashboard/kite-dashboard.component.ts @@ -1,17 +1,19 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, OnDestroy } from '@angular/core'; import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; import { HttpClient } from '@angular/common/http'; -import { Observable } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; +import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators'; import { TotalKiteData } from '../../../@components/leaderboard/leaderboard.interface'; import { environment } from '../../../../environments/environment'; import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; +import { LoaderService } from '../../../@theme/components/loader/loader.service'; @Component({ selector: 'ngx-kite', templateUrl: './kite-dashboard.component.html', styleUrls: ['./kite-dashboard.component.scss'], }) -export class KiteDashboardComponent implements OnInit { +export class KiteDashboardComponent implements OnInit, OnDestroy { latestData: TotalKiteData | null = null; playerId: string | null = null; showgraph: boolean = false; @@ -19,63 +21,80 @@ export class KiteDashboardComponent implements OnInit { isMobileView: boolean = false; hideOnMobile: boolean = false; + + private subscriptions: Subscription = new Subscription(); + constructor( private http: HttpClient, private route: ActivatedRoute, private router: Router, - private breakpointObserver: BreakpointObserver - ) { - this.router.events.subscribe((event) => { - if (event instanceof NavigationEnd) { - this.updateViewBasedOnRoute(); - } - }); - - } + private breakpointObserver: BreakpointObserver, + private loaderService: LoaderService + ) {} ngOnInit(): void { - // Subscribe to route parameters and determine the playerId - this.route.params.subscribe(params => { - this.playerId = params['id']; - this.fetchData(); - this.updateViewBasedOnRoute(); // Update view after fetching data - }); - - // Detect screen size - this.breakpointObserver.observe([Breakpoints.Handset]) - .subscribe(result => { - this.isMobileView = result.matches; - this.checkRoute(); - }); - - // Listen for route changes - this.router.events.subscribe(() => { - this.checkRoute(); - }); - - - // Listen for route changes to update the view - this.router.events.subscribe(() => { - this.updateViewBasedOnRoute(); - }); + this.subscriptions.add( + this.route.params + .pipe( + debounceTime(300), + distinctUntilChanged(), + switchMap(params => { + this.playerId = params['id']; + this.updateViewBasedOnRoute(); + this.loaderService.show(); + + return this.fetchData(); + }) + ) + .subscribe( + data => { + this.renderData(data); + // Hide the loader after data has been fetched + this.loaderService.hide(); + }, + error => { + console.error('Error fetching data:', error); + // Hide the loader on error as well + this.loaderService.hide(); + } + ) + ); + // .subscribe(data => this.renderData(data)) + // ); + + this.subscriptions.add( + this.breakpointObserver.observe([Breakpoints.Handset]) + .subscribe(result => { + this.isMobileView = result.matches; + this.checkRoute(); + }) + ); + + this.subscriptions.add( + this.router.events.subscribe(event => { + if (event instanceof NavigationEnd) { + this.updateViewBasedOnRoute(); + } + }) + ); + } + ngOnDestroy(): void { + this.subscriptions.unsubscribe(); } checkRoute(): void { const currentUrl = this.router.url; - if (currentUrl.includes('/kite/player/all') && this.isMobileView) { - this.hideOnMobile = true; - } else { - this.hideOnMobile = false; - } + this.hideOnMobile = currentUrl.includes('/kite/player/all') && this.isMobileView; } - fetchData(): void { - // Fetch data based on the presence of playerId + fetchData(): Observable { if (this.playerId && this.playerId !== 'all') { - this.fetchDataForPlayer(this.playerId).subscribe(data => this.renderData(data)); + return this.fetchDataForPlayer(this.playerId); + } else if (this.playerId === 'all') { + return this.fetchLatestData(); } else { - this.fetchLatestData().subscribe(data => this.renderData(data)); + return this.fetchLatestData(); } } @@ -89,20 +108,24 @@ export class KiteDashboardComponent implements OnInit { return this.http.get(url); } - renderData(data: TotalKiteData): void { this.latestData = data; - } private updateViewBasedOnRoute(): void { const currentUrl = this.router.url; - this.showgraph = currentUrl === '/kite/player/all'; - this.showBanner = currentUrl === '/kite/player/all'; - } -} - - + if (currentUrl === '/kite/player/all') { + this.showgraph = true; + this.showBanner = true; + } else if (this.playerId && currentUrl === `/kite/player/${this.playerId}`) { + this.showgraph = false; + this.showBanner = false; + } else { + this.showgraph = false; + this.showBanner = false; + } + } +} diff --git a/src/app/pages/kite-competition/kite/kite-api.service.ts b/src/app/pages/kite-competition/kite/kite-api.service.ts index f1af7d9..736d9f1 100644 --- a/src/app/pages/kite-competition/kite/kite-api.service.ts +++ b/src/app/pages/kite-competition/kite/kite-api.service.ts @@ -44,9 +44,9 @@ export class KiteApiService { } - getKitePlayerByUserId(userId: string): Observable { - return this.httpClient.get(`${environment.apiBaseUrl}/kite-players/users/${userId}`); - } + // getKitePlayerByUserId(userId: string): Observable { + // return this.httpClient.get(`${environment.apiBaseUrl}/kite-players/users/${userId}`); + // } // Get Nearest District Data getNearestDistrictData(): Observable { @@ -61,6 +61,8 @@ export class KiteApiService { getAttemptData(playerId: string, attemptTimestamp: string): Observable { + // attemptTimestamp= "2024-08-28T02:02:00Z"; + console.log(attemptTimestamp) ; return this.httpClient.get (`${environment.apiBaseUrl}/kite-players/${playerId}/attempts/${attemptTimestamp}`); } diff --git a/src/app/pages/kite-competition/kite/kite.component.ts b/src/app/pages/kite-competition/kite/kite.component.ts index f24a96c..5298394 100644 --- a/src/app/pages/kite-competition/kite/kite.component.ts +++ b/src/app/pages/kite-competition/kite/kite.component.ts @@ -3,6 +3,7 @@ import { NavigationEnd, Router } from '@angular/router'; import { BreakpointObserver } from '@angular/cdk/layout'; import { SharedDataService } from '../../../services/shared-data.service'; import { Player } from '../../../@components/leaderboard/leaderboard.interface'; +import { LoaderService } from '../../../@theme/components/loader/loader.service'; @Component({ selector: 'ngx-kite', @@ -17,7 +18,8 @@ export class KiteComponent implements OnInit { constructor( private sharedDataService: SharedDataService, private router: Router, - private breakpointObserver: BreakpointObserver + private breakpointObserver: BreakpointObserver, + private loaderService: LoaderService ) { // Listen for route changes and update view accordingly this.router.events.subscribe((event) => { @@ -28,10 +30,12 @@ export class KiteComponent implements OnInit { } ngOnInit(): void { + this.showLoader(); this.sharedDataService.players$.subscribe(players => { this.combinedPlayers = players; console.log('Received players in kiteComponent:', this.combinedPlayers); + this.hideLoader(); }); // Detect if the view is on mobile devices (below 768px) @@ -41,6 +45,13 @@ export class KiteComponent implements OnInit { this.updateViewBasedOnRoute(); // Update view based on current route and device type }); } + private showLoader(): void { + this.loaderService.show(); // Show loader + } + + private hideLoader(): void { + this.loaderService.hide(); // Hide loader + } private updateViewBasedOnRoute(): void { const currentUrl = this.router.url; diff --git a/src/app/pages/kite-competition/player-attempts-chart/player-attempt-chart.component.ts b/src/app/pages/kite-competition/player-attempts-chart/player-attempt-chart.component.ts index 08f9c78..1ef9baa 100644 --- a/src/app/pages/kite-competition/player-attempts-chart/player-attempt-chart.component.ts +++ b/src/app/pages/kite-competition/player-attempts-chart/player-attempt-chart.component.ts @@ -1,17 +1,20 @@ -import { Component, AfterViewInit, OnInit, ViewChildren, QueryList } from '@angular/core'; +import { Component, OnInit, ViewChildren, QueryList, OnDestroy } from '@angular/core'; import { Chart, registerables } from 'chart.js'; import { Attempt, PlayerData } from '../../../@components/leaderboard/leaderboard.interface'; import { KiteApiService } from '../kite/kite-api.service'; import { ActivatedRoute } from '@angular/router'; -import { MatExpansionPanel } from '@angular/material/expansion'; +import { Subject } from 'rxjs'; +import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators'; @Component({ selector: 'ngx-playerattemptchart', styleUrls: ['./player-attempt-chart.component.scss'], templateUrl: './player-attempt-chart.component.html', }) -export class PlayerAttemptChartComponent implements OnInit { +export class PlayerAttemptChartComponent implements OnInit, OnDestroy { playerData: PlayerData | null = null; + attemptDataCache: { [key: string]: any } = {}; + private destroy$ = new Subject(); @ViewChildren('lineChart') lineCharts: QueryList; constructor(private kiteApiService: KiteApiService, private route: ActivatedRoute) { @@ -19,57 +22,81 @@ export class PlayerAttemptChartComponent implements OnInit { } ngOnInit(): void { - this.route.paramMap.subscribe(params => { - const playerId = params.get('id'); - if (playerId) { - this.fetchPlayerData(playerId); - } - }); + this.route.paramMap + .pipe( + debounceTime(300), + distinctUntilChanged(), + takeUntil(this.destroy$) + ) + .subscribe(params => { + const playerId = params.get('id'); + if (playerId) { + this.fetchPlayerData(playerId); + } + }); } fetchPlayerData(playerId: string): void { - this.kiteApiService.getPlayerData(playerId).subscribe( - (data: PlayerData) => { - if (data && data.attempts) { - data.attempts = data.attempts.map((attempt: Attempt) => ({ - ...attempt, - height: Math.round(attempt.height), - })); - } - this.playerData = data; - }, - (error) => { - console.error('Error fetching player data', error); - } - ); + // Fetch data only if playerId is different from the current player + if (!this.playerData || this.playerData.kitePlayer._id !== playerId) { + this.kiteApiService.getPlayerData(playerId) + .pipe(takeUntil(this.destroy$)) + .subscribe( + (data: PlayerData) => { + if (data && data.attempts) { + data.attempts = data.attempts.map((attempt: Attempt) => ({ + ...attempt, + height: Math.round(attempt.height), + })); + } + this.playerData = data; + }, + (error) => { + console.error('Error fetching player data', error); + } + ); + } } fetchAttemptData(playerId: string, attemptTimestamp: string, panelIndex: number): void { - this.kiteApiService.getAttemptData(playerId, attemptTimestamp).subscribe( - (data: { data: { timestamp: string; height: number }[] }) => { - const chartData = { - labels: data.data.map(d => new Date(d.timestamp).toLocaleTimeString([], { - hour: '2-digit', - minute: '2-digit', - hour12: false, - })), - datasets: [{ - label: 'Height', - backgroundColor: 'rgb(102, 187, 106)', - data: data.data.map(d => d.height), - fill: false, - borderColor: 'rgb(102, 187, 106)', - tension: 0.1, - pointRadius: 0, - }], - }; + const cacheKey = `${playerId}-${attemptTimestamp}`; + + // Check if the data is already cached + if (this.attemptDataCache[cacheKey]) { + this.renderChart(panelIndex, this.attemptDataCache[cacheKey]); + } else { + this.kiteApiService.getAttemptData(playerId, attemptTimestamp) + .pipe(takeUntil(this.destroy$)) + .subscribe( + (data: { data: { timestamp: string; height: number }[] }) => { + const chartData = { + labels: data.data.map(d => new Date(d.timestamp).toLocaleTimeString([], { + hour: '2-digit', + minute: '2-digit', + hour12: false, + })), + datasets: [{ + label: 'Height', + backgroundColor: 'rgb(102, 187, 106)', + data: data.data.map(d => d.height), + fill: false, + borderColor: 'rgb(102, 187, 106)', + tension: 0.1, + pointRadius: 0, + }], + }; - this.renderChart(panelIndex, chartData); - }, - (error) => { - console.error('Error fetching attempt data', error); - } - ); + // Cache the data + this.attemptDataCache[cacheKey] = chartData; + + // Render the chart + this.renderChart(panelIndex, chartData); + }, + (error) => { + console.error('Error fetching attempt data', error); + } + ); + } } renderChart(panelIndex: number, chartData: any): void { @@ -93,6 +120,7 @@ export class PlayerAttemptChartComponent implements OnInit { }); } } + onPanelOpened(panelIndex: number): void { const attempt = this.playerData?.attempts[panelIndex]; if (attempt && this.playerData) { @@ -101,4 +129,9 @@ export class PlayerAttemptChartComponent implements OnInit { } } + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } } + diff --git a/src/app/pages/kite-competition/player-data-card/player-data-card.component.ts b/src/app/pages/kite-competition/player-data-card/player-data-card.component.ts index e329f5d..b48c89d 100644 --- a/src/app/pages/kite-competition/player-data-card/player-data-card.component.ts +++ b/src/app/pages/kite-competition/player-data-card/player-data-card.component.ts @@ -1,6 +1,7 @@ import { Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core'; import { TotalKiteData } from '../../../@components/leaderboard/leaderboard.interface'; import { MatTooltip } from '@angular/material/tooltip'; +import { LoaderService } from '../../../@theme/components/loader/loader.service'; @Component({ selector: 'ngx-playerdatacard', @@ -18,6 +19,7 @@ export class PlayerDataCardComponent implements OnInit, OnChanges { img_url: string = '-'; @ViewChild(MatTooltip) tooltip: MatTooltip; + constructor(private loaderService: LoaderService) { } ngOnInit() { this.updateAllValues(); @@ -25,6 +27,7 @@ export class PlayerDataCardComponent implements OnInit, OnChanges { ngOnChanges(changes: SimpleChanges): void { if (changes['data'] && changes['data'].currentValue) { + this.loaderService.show(); this.updateAllValues(); } } @@ -58,6 +61,9 @@ export class PlayerDataCardComponent implements OnInit, OnChanges { if (progress < 1) { requestAnimationFrame(animate); + } else { + + this.loaderService.hide(); } }; @@ -78,6 +84,7 @@ export class PlayerDataCardComponent implements OnInit, OnChanges { }); } else { this.totalAttempts = '-'; + this.loaderService.hide(); } } @@ -90,6 +97,7 @@ export class PlayerDataCardComponent implements OnInit, OnChanges { }); } else { this.totalFlyingtime = '-'; + this.loaderService.hide(); } } @@ -102,6 +110,7 @@ export class PlayerDataCardComponent implements OnInit, OnChanges { }); } else { this.bestHeight = '-'; + this.loaderService.hide(); } } @@ -114,6 +123,7 @@ export class PlayerDataCardComponent implements OnInit, OnChanges { }); } else { this.rank = '-'; + this.loaderService.hide(); } } @@ -122,6 +132,7 @@ export class PlayerDataCardComponent implements OnInit, OnChanges { this.name = this.data.player.name; } else { this.name = '-'; + this.loaderService.hide(); } } @@ -130,6 +141,7 @@ export class PlayerDataCardComponent implements OnInit, OnChanges { this.city = this.data.player.city; } else { this.city = '-'; + this.loaderService.hide(); } } @@ -138,6 +150,7 @@ export class PlayerDataCardComponent implements OnInit, OnChanges { this.img_url = this.data.player.img_url; } else { this.img_url = '-'; + this.loaderService.hide(); } }