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 -----------------------------