fix : added limit of tickets and amount

This commit is contained in:
karthik 2025-07-30 17:00:53 +05:30
parent 855512bedf
commit e66842d510
4 changed files with 145 additions and 16 deletions

View File

@ -32,6 +32,11 @@ export class SelectionService {
const numbers = updated.numbers || [];
const isBoxed = updated.isBoxed ?? false;
// Enforce ticket number limit (1-100)
if (value > 100) {
updated.value = 100;
}
updated.total = 0;
if ((numbers.length > 0 || numbers.includes('F')) && value > 0 && label) {
@ -215,7 +220,10 @@ export class SelectionService {
finalizeCurrentRow() {
const completed = this.currentRow.value;
if (!completed.label || completed.numbers.length === 0 || completed.value <= 0) return;
this.selections.next([...this.selections.value, { ...completed }]);
const currentSelections = this.selections.value;
const totalAmount = currentSelections.reduce((sum, sel) => sum + sel.total, 0);
if (totalAmount + completed.total > 5000) return;
this.selections.next([...currentSelections, { ...completed }]);
this.currentRow.next({ label: '', numbers: [], value: 0, total: 0, isBoxed: false });
}

View File

@ -283,8 +283,9 @@ button {
> div:last-child
button:nth-child(1) {
min-width: 20%;
margin-right: 4rem;
margin-left: 1rem;
/* margin-right: 4rem; */
margin-left: 0px;
padding: 1px;
}
.touch-pad-container
@ -683,3 +684,54 @@ button.ready-to-print {
background-color: #125cac;
color: white;
}
.limit-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.15);
z-index: 2000;
}
.limit-dialog {
background: #ffffff;
border-radius: 8px;
padding: 24px 16px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
min-width: 400px;
box-shadow: 0 3px 16px rgba(0, 0, 0, 0.25);
}
.limit-title {
font-weight: bold;
text-align: center;
font-size: 1.25rem;
margin-bottom: 1.25rem;
}
.limit-message {
text-align: center;
margin-bottom: 1.25rem;
}
.limit-button {
width: 25%;
margin-left: 38%;
padding: 10px 0;
font-size: 1rem;
font-weight: 500;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.2s ease;
}
.limit-button:hover {
background-color: #0056b3;
}

View File

@ -88,7 +88,6 @@
<div class="col-2 column">
<div class="p-2 rounded wrapper-pad" style="background-color: #f1f1f1df">
<div class="row gx-1 gy-1 custom-touchpad">
<div class="col-6">
<button class="btn btn-secondary w-100 number-button" [disabled]="!numericPadEnabled" (click)="enterPadVal('0')">0</button>
</div>
@ -110,7 +109,6 @@
<div class="col-6">
<button class="btn btn-secondary w-100 number-button" [disabled]="!canPrint" (click)="print()">Print</button>
</div>
</div>
</div>
</div>
@ -226,3 +224,27 @@
<button class="btn btn-secondary my-2 w-100" style="opacity: 0.6; pointer-events: none;">TRB3</button>
</div>
</div>
<!-- 🟥 Limit Popup Modal -->
<div
class="limit-overlay"
*ngIf="showLimitPopup"
style="position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(0,0,0,0.15); z-index: 2000;"
(click)="closeLimitPopup()"
>
<div
class="limit-dialog"
(click)="$event.stopPropagation()"
style="background: #fff; border-radius: 8px; padding: 24px 16px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); min-width: 400px; box-shadow: 0 3px 16px rgba(0,0,0,0.25);height: 200px;"
>
<div class="limit-title" style="font-weight: bold; text-align: center; font-size: 1.25rem; margin-bottom: 1.25rem;">
Limit Reached
</div>
<p class="limit-message" style="text-align: center; margin-bottom: 1.25rem;">
Total amount limit of 5000 rupees has been reached. No further selections can be made.
</p>
<button class="limit-button" (click)="closeLimitPopup()">OK</button>
</div>
</div>
</div>

View File

@ -1,6 +1,8 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SelectionService } from '../selection.service/selection.service';
import { Subscription } from 'rxjs';
import { SelectionData } from '../selection.service/selection.service';
@Component({
selector: 'app-touch-pad-menu',
@ -9,7 +11,7 @@ import { SelectionService } from '../selection.service/selection.service';
templateUrl: './touch-pad-menu.component.html',
styleUrls: ['./touch-pad-menu.component.css']
})
export class TouchPadMenuComponent implements OnInit {
export class TouchPadMenuComponent implements OnInit, OnDestroy {
@Input() ticketingActive: boolean = false;
public twoGroupLabels = ['FOR', 'QUI'];
@ -34,6 +36,8 @@ export class TouchPadMenuComponent implements OnInit {
calculatorOpen = false;
calcDisplay = '';
maxRowsReached: boolean = false;
totalAmountLimitReached: boolean = false;
showLimitPopup: boolean = false;
disabledLabels: string[] = ['SHW', 'SJP', '.'];
@ -63,14 +67,37 @@ export class TouchPadMenuComponent implements OnInit {
// TRE popup
trePopupVisible = false;
private currentRowSubscription: Subscription | null = null;
private selectionsSubscription: Subscription | null = null;
private currentTotal: number = 0;
private currentSelections: SelectionData[] = [];
constructor(private selectionService: SelectionService) {}
ngOnInit() {
this.labelRowsFlat = this.labelRows.flat();
this.numbersFlat = this.numberRows.flat();
this.selectionService.selections$.subscribe(selections => {
this.selectionsSubscription = this.selectionService.selections$.subscribe(selections => {
this.currentSelections = selections;
this.maxRowsReached = selections.length >= 5;
const totalAmount = selections.reduce((sum, selection) => sum + selection.total, 0);
this.totalAmountLimitReached = totalAmount >= 5000;
if (this.totalAmountLimitReached) {
this.showLimitPopup = true;
}
});
this.currentRowSubscription = this.selectionService.currentRow$.subscribe(row => {
this.currentTotal = row.total;
});
}
ngOnDestroy() {
if (this.currentRowSubscription) {
this.currentRowSubscription.unsubscribe();
}
if (this.selectionsSubscription) {
this.selectionsSubscription.unsubscribe();
}
}
get labelRows() {
@ -140,13 +167,17 @@ export class TouchPadMenuComponent implements OnInit {
}
isLabelDisabled(label: string): boolean {
return this.disabledLabels.includes(label);
return this.disabledLabels.includes(label) || this.totalAmountLimitReached;
}
selectLabel(label: string) {
if (this.totalAmountLimitReached) {
this.showLimitPopup = true;
return;
}
if (label === 'TRE') {
this.trePopupVisible = true;
return; // Stop further execution until popup interaction
return;
}
this.selectedLabel = label;
this.selectedNumbers = [];
@ -171,7 +202,7 @@ export class TouchPadMenuComponent implements OnInit {
}
selectNumber(number: number) {
if (!this.selectedLabel) return;
if (!this.selectedLabel || this.totalAmountLimitReached) return;
// TAN Box mode: freestyle selection with dash-separated format
if (this.selectedLabel === 'TAN' && this.isBoxed) {
@ -264,7 +295,7 @@ export class TouchPadMenuComponent implements OnInit {
if (this.selectedLabel === 'TAN' || this.multiLegLabels.includes(this.selectedLabel || '') || this.twoGroupLabels.includes(this.selectedLabel || '')) {
return false;
}
return this.selectedNumbers.includes(number);
return this.selectedNumbers.includes(number) || this.totalAmountLimitReached;
}
onPadEnter() {
@ -311,11 +342,14 @@ export class TouchPadMenuComponent implements OnInit {
}
enterPadVal(key: string) {
if (!this.numericPadEnabled) return;
if (!this.numericPadEnabled || this.totalAmountLimitReached) return;
if (key === 'X') {
this.padValue = '';
} else if (/[0-9]/.test(key)) {
// Limit ticket number to 1-100 for all labels
const currentValue = parseInt(this.padValue + key) || 0;
if (currentValue > 100) return;
this.padValue += key;
}
@ -335,6 +369,11 @@ export class TouchPadMenuComponent implements OnInit {
}
print() {
const selectionsTotal = this.currentSelections.reduce((sum, sel) => sum + sel.total, 0);
if (selectionsTotal + this.currentTotal > 5000) {
this.showLimitPopup = true;
return;
}
this.selectionService.finalizeCurrentRow();
this.resetSelections();
}
@ -367,6 +406,7 @@ export class TouchPadMenuComponent implements OnInit {
}
toggleBoxMode() {
if (this.totalAmountLimitReached) return;
this.isBoxed = !this.isBoxed;
const value = parseFloat(this.padValue) || 0;
// For TAN Box mode, reset to freestyle selection
@ -536,6 +576,7 @@ export class TouchPadMenuComponent implements OnInit {
}
canUseField(): boolean {
if (this.totalAmountLimitReached) return false;
if (this.selectedLabel === 'FOR' || this.selectedLabel === 'QUI') {
if (!this.isFirstGroupComplete && this.firstGroup.length === 0) {
return true;
@ -562,6 +603,7 @@ export class TouchPadMenuComponent implements OnInit {
}
openFieldModal() {
if (this.totalAmountLimitReached) return;
if (['FOR', 'QUI', 'TAN'].includes(this.selectedLabel || '') || this.multiLegLabels.includes(this.selectedLabel || '')) {
this.handleFieldForSpecialLabels();
} else {
@ -647,6 +689,7 @@ export class TouchPadMenuComponent implements OnInit {
}
openPoolReplaceModal() {
if (this.totalAmountLimitReached) return;
this.poolReplaceOpen = true;
}
@ -681,4 +724,8 @@ export class TouchPadMenuComponent implements OnInit {
closeTrePopup() {
this.trePopupVisible = false;
}
closeLimitPopup() {
this.showLimitPopup = false;
}
}