diff --git a/btc-UI/src/app/components/selection.service/label-restriction.service.ts b/btc-UI/src/app/components/selection.service/label-restriction.service.ts index 3a6105d..3109d4a 100644 --- a/btc-UI/src/app/components/selection.service/label-restriction.service.ts +++ b/btc-UI/src/app/components/selection.service/label-restriction.service.ts @@ -1,10 +1,10 @@ +// label-restriction.service.ts import { Injectable } from '@angular/core'; import { SelectionData } from '../selection.service/selection.service'; -// Define mutually exclusive label groups export const LABEL_GROUPS: { [key: string]: string[] } = { - groupA: ['WIN', 'SHP', 'THP', 'PLC', 'SHW'], - groupB: ['FOR', 'QUI', 'TAN', 'EXA'], + groupA: ['WNP', 'SHP', 'THP', 'PLP', 'SHW'], + groupB: ['FRP', 'QNP', 'TNP', 'EXA'], groupWSP: ['WSP'], groupTRE: ['TRE'], groupMJP: ['MJP'], @@ -19,14 +19,22 @@ Object.entries(LABEL_GROUPS).forEach(([group, labels]) => { @Injectable({ providedIn: 'root' }) export class LabelRestrictionService { - getBlockedLabels(selections: SelectionData[]): Set { + // accept optional currentLabel + getBlockedLabels(selections: SelectionData[], currentLabel?: string | null): Set { const selectedGroups = new Set(); + + // existing finalized selections for (const row of selections) { if (row.label && LABEL_TO_GROUP[row.label]) { selectedGroups.add(LABEL_TO_GROUP[row.label]); } } + // also consider in-progress/current label (if provided) + if (currentLabel && LABEL_TO_GROUP[currentLabel]) { + selectedGroups.add(LABEL_TO_GROUP[currentLabel]); + } + const blockLabels = new Set(); if (selectedGroups.size > 0) { // Block all labels from groups not already selected @@ -36,10 +44,10 @@ export class LabelRestrictionService { } }); - // Special rule for WSP: if WSP is selected, only allow WIN, SHP, THP in the three rows + // Special rule for WSP: if WSP is selected, only allow WNP, SHP, PLP (others blocked) if (selectedGroups.has('groupWSP')) { Object.keys(LABEL_TO_GROUP).forEach(label => { - if (!['WIN', 'SHP', 'THP'].includes(label)) { + if (!['WNP', 'SHP', 'PLP'].includes(label)) { blockLabels.add(label); } }); @@ -48,4 +56,4 @@ export class LabelRestrictionService { return blockLabels; } -} \ No newline at end of file +} 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 202af46..294b6c1 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 @@ -143,7 +143,10 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy { this.maxRowsReached = selections.length >= 5; const totalAmount = selections.reduce((sum: number, selection: SelectionData) => sum + (selection.total || 0), 0); this.totalAmountLimitReached = totalAmount >= 5000; - this.blockedLabels = this.labelRestrictionService.getBlockedLabels(selections); + + // NEW: + this.refreshBlockedLabels(this.selectedLabel); + if (!this.totalAmountLimitReached) { this.showLimitPopup = false; } @@ -389,6 +392,8 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy { this.runnerCount = this.getRunnerCountForLeg(this.multiLegBaseRaceIdx, 0) || 12; this.numbers = Array.from({ length: 30 }, (_, i) => i + 1); this.numbersFlat = this.numberRows.flat(); + // Call after pool change + this.refreshBlockedLabels(label); } else { this.currentPool = null; this.multiLegBaseRaceIdx = 0; @@ -399,6 +404,8 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy { }); // --- NEW: Update actualRunners for single race --- this.setActualRunners(); + // Call after pool change + this.refreshBlockedLabels(label); } //----------------------------------ADDED THIS ----------------------------------------------------- @@ -421,9 +428,13 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy { const totalExisting = currentSelections.reduce((sum, r) => sum + r.total, 0); if (totalExisting + totalNew <= 5000) { this.selectionService.setSelections([...currentSelections, ...blankRows]); + // Call after setSelections + this.refreshBlockedLabels(label); } } this.selectionService.updatePartial({ label: '', numbers: [], value: 0, total: 0 }); + // Call before return in WSP + this.refreshBlockedLabels(label); return; } //----------------------------------ended here---------------------------------------------------- @@ -440,6 +451,8 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy { this.multiLegGroups = [[], [], [], [], []]; this.selectionService.updatePartial({ label }); + // recompute blocked labels including newly-selected label + this.refreshBlockedLabels(label); } private getBaseRaceIndexForPool(poolName: string): number { @@ -564,6 +577,8 @@ if (this.twoGroupLabels.includes(this.selectedLabel || '')) { return sel; }); this.selectionService.setSelections(updated); + // Call after setSelections + this.refreshBlockedLabels(this.selectedLabel); } } } @@ -630,6 +645,8 @@ if (this.twoGroupLabels.includes(this.selectedLabel || '')) { }); this.selectionService.setSelections(updatedSelections); + // Call after setSelections + this.refreshBlockedLabels(this.selectedLabel); this.padValue = ''; this.updateCanPrint(); } @@ -662,6 +679,8 @@ if (this.twoGroupLabels.includes(this.selectedLabel || '')) { }); this.selectionService.setSelections(updatedSelections); + // Call after setSelections + this.refreshBlockedLabels(this.selectedLabel); // Only increment stage if not at the last stage (PLP) if (this.wspTicketStage < 2) { @@ -759,6 +778,8 @@ if (this.twoGroupLabels.includes(this.selectedLabel || '')) { }); this.selectionService.setSelections(updatedSelections); + // Call after setSelections + this.refreshBlockedLabels(this.selectedLabel); const currentTotal = updatedSelections.find(sel => sel.label === targetLabel)?.total || 0; if (currentTotal === 0 && value > 0) { @@ -766,6 +787,8 @@ if (this.twoGroupLabels.includes(this.selectedLabel || '')) { this.selectionService.setSelections( updatedSelections.filter(sel => sel.label !== targetLabel || sel.numbers.length > 0) ); + // Call after setSelections + this.refreshBlockedLabels(this.selectedLabel); this.wspTicketStage = 0; this.padValue = ''; this.selectedNumbers = []; @@ -937,9 +960,13 @@ if (this.twoGroupLabels.includes(this.selectedLabel || '')) { const currentSelections = this.selectionService.getSelections(); const nonWSPSelections = currentSelections.filter(sel => !['WNP', 'SHP', 'PLP'].includes(sel.label)); this.selectionService.setSelections([...nonWSPSelections, ...virtualRows]); + // Call after setSelections + this.refreshBlockedLabels(this.selectedLabel); } this.selectionService.finalizeCurrentRow(); + // Call after finalizeCurrentRow + this.refreshBlockedLabels(null); this.resetSelections(); } @@ -1138,14 +1165,14 @@ const winLabels = allRows.map(row => { // displayNumbers = displayNumbers.flatMap((n, idx, arr) => { // if (n === 'F') { // const horses = this.getHorseNumbersForSelectedRace().map(num => num.toString()).join(','); -// const isFirst = idx === 0; -// const isLast = idx === arr.length - 1; -// if (isFirst && !isLast) return [`${horses}-`]; -// if (!isFirst && isLast) return [`-${horses}`]; -// if (isFirst && isLast) return [horses]; // only F -// return [`-${horses}-`]; -// } -// return [n]; + // const isFirst = idx === 0; + // const isLast = idx === arr.length - 1; + // if (isFirst && !isLast) return [`${horses}-`]; + // if (!isFirst && isLast) return [`-${horses}`]; + // if (isFirst && isLast) return [horses]; // only F + // return [`-${horses}-`]; + // } + // return [n]; // }); displayNumbers = displayNumbers.flatMap((n) => { if (n === 'F') { @@ -1507,6 +1534,8 @@ try { //--------------------Ended Print here ----------------------------- this.selectionService.finalizeCurrentRow(); + // Call after finalizeCurrentRow + this.refreshBlockedLabels(null); this.resetSelections(); } @@ -1514,6 +1543,7 @@ try { erase() { this.selectionService.clearSelections(); this.resetSelections(); + this.refreshBlockedLabels(null); this.cdr.markForCheck(); // <-- Force UI update } @@ -1539,8 +1569,8 @@ try { this.fieldInput = ''; this.fieldFEntered = false; this.wspTicketStage = 0; - // Explicitly reset blocked labels - this.blockedLabels = this.labelRestrictionService.getBlockedLabels([]); + // Explicitly reset blocked labels (no current label) + this.refreshBlockedLabels(null); this.updateCanPrint(); this.sharedStateService.updateSharedData({ type: 'multiLegPoolEnd', value: null }); this.cdr.markForCheck(); // <-- Force UI update @@ -1823,6 +1853,8 @@ try { this.poolReplaceOpen = false; // Update selection service with new label this.selectionService.updatePartial({ label }); + // recompute blocked labels including newly-selected label + this.refreshBlockedLabels(label); } closePoolReplaceModal() { this.poolReplaceOpen = false; } @@ -1863,6 +1895,8 @@ try { this.runnerCount = this.getRunnerCountForLeg(this.multiLegBaseRaceIdx, 0) || 12; this.numbers = Array.from({ length: 30 }, (_, i) => i + 1); this.numbersFlat = this.numberRows.flat(); + // Call after pool change + this.refreshBlockedLabels('TRE'); } closeTrePopup() { this.trePopupVisible = false; } @@ -1927,4 +1961,14 @@ try { currentRow.value <= 100 && currentRow.total > 0; } -} + + // add this in the component class (near other helpers) + private refreshBlockedLabels(currentLabel?: string | null) { + // Pass finalized selections and optionally the in-progress/current label + const finalized = this.selectionService.getSelections(); + this.blockedLabels = this.labelRestrictionService.getBlockedLabels(finalized, currentLabel ?? this.selectedLabel); + console.log('[DEBUG] refreshBlockedLabels -> selectedLabel:', currentLabel ?? this.selectedLabel, 'blocked:', Array.from(this.blockedLabels)); + // Ensure OnPush UI updates + try { this.cdr.markForCheck(); } catch (e) { /* ignore */ } + } +} \ No newline at end of file