diff --git a/btc-UI/src/app/components/navbar/navbar.component.html b/btc-UI/src/app/components/navbar/navbar.component.html index 46e392f..8240698 100755 --- a/btc-UI/src/app/components/navbar/navbar.component.html +++ b/btc-UI/src/app/components/navbar/navbar.component.html @@ -42,7 +42,7 @@ class="nav-dropdown w-50 text-start ps-3" (click)="openRaceModal()" > - Race No. | {{ currentLegRaceDisplay ? currentLegRaceDisplay : 'Race ' + selectedRace }} + Race No. | {{ selectedRace }}
@@ -95,7 +95,7 @@ class="nav-dropdown w-100 text-end pe-3" (click)="openRaceModal()" > - Race No. | {{ currentLegRaceDisplay ? currentLegRaceDisplay : 'Race ' + selectedRace }} + Race No. | {{ selectedRace }}
diff --git a/btc-UI/src/app/components/navbar/navbar.component.ts b/btc-UI/src/app/components/navbar/navbar.component.ts index a5e38fe..5b746c9 100755 --- a/btc-UI/src/app/components/navbar/navbar.component.ts +++ b/btc-UI/src/app/components/navbar/navbar.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, HostListener, OnDestroy } from '@angular/core'; +import { Component, OnInit, HostListener, OnDestroy, NgZone } from '@angular/core'; import { CommonModule } from '@angular/common'; import { BtcService } from '../../service/btc.service'; import { Router } from '@angular/router'; @@ -37,8 +37,10 @@ export class NavbarComponent implements OnInit, OnDestroy { selectedRaceId: number = 0; enabledHorseNumbers: number[] = []; - multiLegBaseRaceIdx: number = 0; // Track base race index for multi-leg pools - currentPool: string | null = null; // Track current multi-leg pool + multiLegBaseRaceIdx: number = 0; + currentPool: string | null = null; + + private prevEnabledKey = ''; // For memoization wallet = { withdraw: 0, @@ -67,12 +69,17 @@ export class NavbarComponent implements OnInit, OnDestroy { constructor( private btcService: BtcService, private router: Router, - private sharedStateService: SharedStateService + private sharedStateService: SharedStateService, + private zone: NgZone // <-- Add NgZone ) {} ngOnInit() { - this.updateDateTime(); - setInterval(() => this.updateDateTime(), 1000); + // Use NgZone to run setInterval outside Angular's change detection + this.zone.runOutsideAngular(() => { + setInterval(() => { + this.zone.run(() => this.updateDateTime()); + }, 1000); + }); this.subscription = interval(5000) .pipe( @@ -91,16 +98,7 @@ export class NavbarComponent implements OnInit, OnDestroy { } }); - const cachedData = localStorage.getItem('raceCardData'); - if (cachedData) { - this.raceCardData = JSON.parse(cachedData); - console.log('📦 Loaded race card from localStorage:', this.raceCardData); - this.selectedVenue = this.raceCardData?.Venue || 'Select Venue'; - this.updateEnabledHorseNumbers(); - } else { - this.raceCardData = { raceVenueRaces: { races: [] }, pools: {} }; - console.warn('⚠️ No race card data found in localStorage.'); - } + this.sharedStateService.sharedData$.subscribe(data => { if (data.type === 'currentLegRace') { @@ -150,22 +148,29 @@ export class NavbarComponent implements OnInit, OnDestroy { private updateEnabledHorseNumbersForMultiLeg(baseRaceIdx: number) { const raceCardData = this.raceCardData?.raceVenueRaces?.races || []; - let combinedHorseNumbers: number[] = []; const legCount = this.getLegCountForLabel(); + const key = `${this.currentPool}-${baseRaceIdx}-${legCount}`; - for (let i = 0; i < legCount; i++) { - const raceIdx = this.getRaceForLeg(this.currentPool || '', i) - 1; + if (this.prevEnabledKey === key) return; // 🧠 Memoization + this.prevEnabledKey = key; + + let combinedHorseNumbers: number[] = []; + + const raceIndices = Array.from({ length: legCount }, (_, i) => + this.getRaceForLeg(this.currentPool || '', i) - 1 + ); + + for (const raceIdx of raceIndices) { const race = raceCardData[raceIdx] || []; if (Array.isArray(race)) { const horses = race .map((runner: any) => runner?.horseNumber) .filter((n: number) => typeof n === 'number' && n >= 1 && n <= 30); - combinedHorseNumbers = combinedHorseNumbers.concat(horses); + combinedHorseNumbers.push(...horses); } } - combinedHorseNumbers = Array.from(new Set(combinedHorseNumbers)); - this.enabledHorseNumbers = combinedHorseNumbers; + this.enabledHorseNumbers = Array.from(new Set(combinedHorseNumbers)); this.sharedStateService.updateSharedData({ type: 'enabledHorseNumbers', @@ -176,7 +181,6 @@ export class NavbarComponent implements OnInit, OnDestroy { } private getLegCountForLabel(): number { - if (!this.currentPool) return 3; switch (this.currentPool) { case 'mjp1': return 4; case 'jkp1': return 5; @@ -214,6 +218,17 @@ export class NavbarComponent implements OnInit, OnDestroy { } openVenueModal() { + + const cachedData = localStorage.getItem('raceCardData'); + if (cachedData) { + this.raceCardData = JSON.parse(cachedData); + // console.log('📦 Loaded race card from localStorage:', this.raceCardData); // comment out for perf + this.selectedVenue = this.raceCardData?.Venue || 'Select Venue'; + this.updateEnabledHorseNumbers(); + } else { + this.raceCardData = { raceVenueRaces: { races: [] }, pools: {} }; + // console.warn('⚠️ No race card data found in localStorage.'); // comment out for perf + } console.log('[MODAL] Opening venue modal'); this.showVenueModal = true; } @@ -225,8 +240,6 @@ export class NavbarComponent implements OnInit, OnDestroy { const venueIndex = Object.keys(this.raceCardData?.raceVenueRaces?.races || []) .findIndex((_, idx) => idx === this.selectedRaceId); - - if (venueIndex !== -1) { this.raceData = this.raceCardData.raceVenueRaces.races[venueIndex] || []; } @@ -253,8 +266,6 @@ export class NavbarComponent implements OnInit, OnDestroy { }); console.log('[VENUE] Venue resolved to:', this.selectedVenue); - console.log('[VENUE] Venue sent to sharedStateService'); - this.closeModals(); } @@ -293,12 +304,12 @@ export class NavbarComponent implements OnInit, OnDestroy { this.enabledHorseNumbers = []; } - console.log('[HORSE NUMBERS] Enabled horse numbers:', this.enabledHorseNumbers); - this.sharedStateService.updateSharedData({ type: 'enabledHorseNumbers', value: this.enabledHorseNumbers, }); + + console.log('[HORSE NUMBERS] Enabled horse numbers:', this.enabledHorseNumbers); } selectHorseNumber(number: number) { @@ -358,4 +369,9 @@ export class NavbarComponent implements OnInit, OnDestroy { this.subscription.unsubscribe(); } } -} \ No newline at end of file + + // Add trackByHorse for use in *ngFor + trackByHorse(index: number, item: number): number { + return item; + } +} diff --git a/btc-UI/src/app/components/touch-pad-menu/touch-pad-menu.component.ts b/btc-UI/src/app/components/touch-pad-menu/touch-pad-menu.component.ts index 1a365ad..462a04b 100755 --- a/btc-UI/src/app/components/touch-pad-menu/touch-pad-menu.component.ts +++ b/btc-UI/src/app/components/touch-pad-menu/touch-pad-menu.component.ts @@ -1,4 +1,11 @@ -import { Component, Input, OnInit, OnDestroy } from '@angular/core'; +import { + Component, + Input, + OnInit, + OnDestroy, + NgZone, + ChangeDetectionStrategy +} from '@angular/core'; import { CommonModule } from '@angular/common'; import { Subscription } from 'rxjs'; import { SelectionService, SelectionData } from '../selection.service/selection.service'; @@ -10,7 +17,8 @@ import { LabelRestrictionService } from '../selection.service/label-restriction. standalone: true, imports: [CommonModule], templateUrl: './touch-pad-menu.component.html', - styleUrls: ['./touch-pad-menu.component.css'] + styleUrls: ['./touch-pad-menu.component.css'], + changeDetection: ChangeDetectionStrategy.OnPush // 🔥 CRUCIAL for performance }) export class TouchPadMenuComponent implements OnInit, OnDestroy { @Input() ticketingActive: boolean = false; @@ -79,10 +87,16 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy { private currentTotal: number = 0; private currentSelections: SelectionData[] = []; + enabledHorseNumbers: number[] = []; + prevEnabledKey: string = ''; + + raceCardData: any = {}; + constructor( private selectionService: SelectionService, private sharedStateService: SharedStateService, - private labelRestrictionService: LabelRestrictionService + private labelRestrictionService: LabelRestrictionService, + private ngZone: NgZone // <-- inject NgZone ) {} @@ -133,6 +147,12 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy { } }); + const data = localStorage.getItem('raceCardData'); + if (data) { + this.raceCardData = JSON.parse(data); + } else { + this.raceCardData = {}; + } } ngOnDestroy() { @@ -911,7 +931,7 @@ const winLabels = allRows.map(row => { this.erase(); // ✅ Clear selections after successful print }); - // this.erase(); // ✅ Clear selections after successful print + this.erase(); // ✅ Clear selections after successful print //--------------------Ended Print here -----------------------------