diff --git a/btc-UI/electron/main.js b/btc-UI/electron/main.js
index b105e91..d745384 100644
--- a/btc-UI/electron/main.js
+++ b/btc-UI/electron/main.js
@@ -1,9 +1,11 @@
+// main.js
const { app, BrowserWindow, screen, ipcMain } = require('electron');
const path = require('path');
const fs = require('fs');
let mainWindow;
let screenWindow;
+let currentSharedData = null; // Store latest data for initial sync
function createWindows() {
const displays = screen.getAllDisplays();
@@ -18,7 +20,7 @@ function createWindows() {
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
- }
+ },
});
mainWindow.loadURL('http://10.74.231.124:4200/login');
@@ -33,15 +35,30 @@ function createWindows() {
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
- }
+ },
});
screenWindow.loadURL('http://10.74.231.124:4200/shared-display');
- ipcMain.on('open-second-screen', () => screenWindow.show());
+ // Handle opening second screen and send initial data
+ ipcMain.on('open-second-screen', () => {
+ screenWindow.show();
+ if (currentSharedData && screenWindow.webContents) {
+ screenWindow.webContents.send('update-shared-data', currentSharedData);
+ }
+ });
+
ipcMain.on('close-second-screen', () => screenWindow.hide());
- // ✅ IPC to return BTID
+ // Handle syncing data
+ ipcMain.on('sync-shared-data', (event, data) => {
+ currentSharedData = data; // Store latest data
+ if (screenWindow && screenWindow.webContents) {
+ screenWindow.webContents.send('update-shared-data', data);
+ }
+ });
+
+ // Handle BTID request
ipcMain.handle('get-btid', () => {
try {
const filePath = path.join(process.env.HOME || process.env.USERPROFILE, 'BTID', 'betting.txt');
@@ -56,4 +73,4 @@ function createWindows() {
}
app.whenReady().then(createWindows);
-app.on('window-all-closed', () => app.quit());
+app.on('window-all-closed', () => app.quit());
\ No newline at end of file
diff --git a/btc-UI/electron/preload.js b/btc-UI/electron/preload.js
index 8492231..3d1c198 100644
--- a/btc-UI/electron/preload.js
+++ b/btc-UI/electron/preload.js
@@ -1,9 +1,12 @@
+// preload.js
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
openSecondScreen: () => ipcRenderer.send('open-second-screen'),
closeSecondScreen: () => ipcRenderer.send('close-second-screen'),
-
- // ✅ Ask main process for Btid
- getBtid: () => ipcRenderer.invoke('get-btid')
+ getBtid: () => ipcRenderer.invoke('get-btid'),
+ // New: Send data to main process
+ syncSharedData: (data) => ipcRenderer.send('sync-shared-data', data),
+ // New: Receive data in second window
+ onUpdateSharedData: (callback) => ipcRenderer.on('update-shared-data', (event, data) => callback(data)),
});
\ No newline at end of file
diff --git a/btc-UI/src/app/components/middle-section/middle-section.component.ts b/btc-UI/src/app/components/middle-section/middle-section.component.ts
index 3f6831c..c1a5437 100755
--- a/btc-UI/src/app/components/middle-section/middle-section.component.ts
+++ b/btc-UI/src/app/components/middle-section/middle-section.component.ts
@@ -1,4 +1,4 @@
-import { Component, Input, OnInit, OnDestroy, Output, EventEmitter } from '@angular/core';
+import { Component, Input, OnInit, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SelectionService, SelectionData } from '../selection.service/selection.service';
import { Subscription } from 'rxjs';
@@ -8,17 +8,16 @@ import { Subscription } from 'rxjs';
standalone: true,
imports: [CommonModule],
templateUrl: './middle-section.component.html',
- styleUrls: ['./middle-section.component.css']
+ styleUrls: ['./middle-section.component.css'],
})
export class MiddleSectionComponent implements OnInit, OnDestroy {
@Input() containerHeight: string = '50vh';
@Input() eraseTrigger: any;
summaryRows = Array.from({ length: 4 });
-
filledRows: SelectionData[] = [];
currentRow: SelectionData = { label: '', numbers: [], value: 0, total: 0 };
grandTotal: number = 0;
- salesTotal: number = 0;
+ salesTotal: number = 0;
receiveTotal: number = 0;
totalClicks: number = 0;
showConfirmButton: boolean = false;
@@ -26,7 +25,6 @@ export class MiddleSectionComponent implements OnInit, OnDestroy {
showRepeatTicket: boolean = false;
confirmRepeat: boolean = false;
showPrintButton: boolean = false;
-
private selections: SelectionData[] = [];
private sub1!: Subscription;
private sub2!: Subscription;
@@ -34,12 +32,12 @@ export class MiddleSectionComponent implements OnInit, OnDestroy {
constructor(private selectionService: SelectionService) {}
ngOnInit() {
- this.sub1 = this.selectionService.selections$.subscribe(data => {
+ this.sub1 = this.selectionService.selections$.subscribe((data) => {
this.selections = data;
this.updateFilledRows(this.selections, this.currentRow);
});
- this.sub2 = this.selectionService.currentRow$.subscribe(row => {
+ this.sub2 = this.selectionService.currentRow$.subscribe((row) => {
this.currentRow = row;
this.updateFilledRows(this.selections, row);
});
@@ -51,130 +49,133 @@ export class MiddleSectionComponent implements OnInit, OnDestroy {
}
}
+ // Helper to sync data to second screen
+ private syncToSecondScreen() {
+ if (window.electronAPI && window.electronAPI.syncSharedData) {
+ window.electronAPI.syncSharedData({
+ filledRows: this.filledRows,
+ summaryRows: [
+ { col1: 'Sales', col2: this.totalClicks, col3: this.salesTotal },
+ { col1: 'Cancel', col2: 0, col3: 0 },
+ { col1: 'Payout', col2: 0, col3: 0 },
+ { col1: 'Receive', col2: this.totalClicks, col3: this.receiveTotal },
+ ],
+ grandTotal: this.grandTotal,
+ salesTotal: this.salesTotal,
+ receiveTotal: this.receiveTotal,
+ totalClicks: this.totalClicks,
+ });
+ }
+ }
+
updateFilledRows(saved: SelectionData[], current: SelectionData) {
const rows: SelectionData[] = [...saved];
- if (rows.length < 5 && current.label) rows.push(current); // Include current row if label is selected
-
+ if (rows.length < 5 && current.label) rows.push(current);
const emptyCount = Math.max(5 - rows.length, 0);
const emptyRows = Array.from({ length: emptyCount }, () => ({
label: '',
numbers: [],
value: 0,
- total: 0
+ total: 0,
}));
-
this.filledRows = [...rows, ...emptyRows].slice(0, 5);
this.calculateTotal();
-
// Show Confirm button only if at least one row has data (label and numbers)
- // and only after repeat is clicked (showRepeatTicket flag)
- this.showConfirmButton = this.showRepeatTicket && this.filledRows.some(
- row => row.label && row.numbers && row.numbers.length > 0
- );
-
+ // and only after repeat is clicked (showRepeatTicket flag)
+ this.showConfirmButton =
+ this.showRepeatTicket &&
+ this.filledRows.some((row) => row.label && row.numbers && row.numbers.length > 0);
// Hide Print button if Confirm is hidden
if (!this.showConfirmButton) {
this.showPrintButton = false;
}
+ this.syncToSecondScreen(); // Sync after updating rows
}
+
showSalesTotal: boolean = false;
calculateTotal() {
- this.grandTotal = this.filledRows.reduce((sum, row) => sum + (row.total || 0), 0);
-
- let storedTotal = 0;
- try {
- const storedTickets = JSON.parse(localStorage.getItem('localTickets') || '[]');
- if (Array.isArray(storedTickets)) {
- storedTotal = storedTickets
- .filter(ticket => ticket.type === 'ticket')
- .reduce((sum: number, ticket: any) => sum + (ticket.totalAmount || 0), 0);
+ this.grandTotal = this.filledRows.reduce((sum, row) => sum + (row.total || 0), 0);
+ let storedTotal = 0;
+ try {
+ const storedTickets = JSON.parse(localStorage.getItem('localTickets') || '[]');
+ if (Array.isArray(storedTickets)) {
+ storedTotal = storedTickets
+ .filter((ticket) => ticket.type === 'ticket')
+ .reduce((sum: number, ticket: any) => sum + (ticket.totalAmount || 0), 0);
+ }
+ } catch (e) {
+ console.error('❌ Failed to parse localTickets from localStorage:', e);
}
- } catch (e) {
- console.error('❌ Failed to parse localTickets from localStorage:', e);
- }
-
// 👇 Only show printed totals until print happens
- const hasPrinted = localStorage.getItem('hasPrinted') === 'true';
-
- if (hasPrinted) {
- this.salesTotal = storedTotal;
- this.receiveTotal = storedTotal;
- } else {
- this.salesTotal = storedTotal; // do NOT include grandTotal yet
- this.receiveTotal = storedTotal;
+ const hasPrinted = localStorage.getItem('hasPrinted') === 'true';
+ if (hasPrinted) {
+ this.salesTotal = storedTotal;
+ this.receiveTotal = storedTotal;
+ } else {
+ this.salesTotal = storedTotal;
+ this.receiveTotal = storedTotal;
+ }
+ this.totalClicks = Number(localStorage.getItem('printClickCount') || '0');
+ this.showSalesTotal = hasPrinted;
+ this.syncToSecondScreen(); // Sync after calculating totals
}
- this.totalClicks = Number(localStorage.getItem('printClickCount') || '0');
-
- // 👇 Toggle visibility based on localStorage flag
- this.showSalesTotal = localStorage.getItem('hasPrinted') === 'true';
-}
-
-
-
repeat() {
- try {
- const storedTickets = localStorage.getItem('localTicketsnew');
- if (storedTickets) {
- const tickets = JSON.parse(storedTickets);
- const latestTicket = Array.isArray(tickets)
- ? (tickets.length > 0 ? tickets[tickets.length - 1] : null)
- : tickets;
-
- if (latestTicket && latestTicket.winLabels) {
- // Pass totalAmount as a fallback for missing totals
- const parsedRows = this.parseWinLabelsToRows(
- latestTicket.winLabels,
- latestTicket.totalAmount
- );
-
- // ✅ Always make sure we have exactly 5 rows
- this.updateFilledRows(parsedRows, { label: '', numbers: [], value: 0, total: 0 });
-
- console.log('📜 Updated Filled Rows:', parsedRows);
- this.showConfirmButton = true;
- this.showPrintButton = false;
- this.lastTicket = latestTicket;
+ try {
+ const storedTickets = localStorage.getItem('localTicketsnew');
+ if (storedTickets) {
+ const tickets = JSON.parse(storedTickets);
+ const latestTicket = Array.isArray(tickets)
+ ? tickets.length > 0
+ ? tickets[tickets.length - 1]
+ : null
+ : tickets;
+ if (latestTicket && latestTicket.winLabels) {
+ const parsedRows = this.parseWinLabelsToRows(latestTicket.winLabels, latestTicket.totalAmount);
+ // ✅ Always make sure we have exactly 5 rows
+ this.updateFilledRows(parsedRows, { label: '', numbers: [], value: 0, total: 0 });
+ console.log('📜 Updated Filled Rows:', parsedRows);
+ this.showConfirmButton = true;
+ this.showPrintButton = false;
+ this.lastTicket = latestTicket;
+ this.showRepeatTicket = true;
+ this.syncToSecondScreen(); // Sync after repeat
+ } else {
+ console.warn('⚠️ No valid ticket data found in localStorage.');
+ }
} else {
- console.warn('⚠️ No valid ticket data found in localStorage.');
+ console.warn('⚠️ No tickets found in localStorage.');
}
- } else {
- console.warn('⚠️ No tickets found in localStorage.');
+ } catch (error) {
+ console.error('❌ Failed to load ticket from localStorage:', error);
}
- } catch (error) {
- console.error('❌ Failed to load ticket from localStorage:', error);
}
-}
-parseWinLabelsToRows(winLabels: string, fallbackTotal?: number): SelectionData[] {
+ parseWinLabelsToRows(winLabels: string, fallbackTotal?: number): SelectionData[] {
return (winLabels.split('\n') as string[])
- .map(line => {
- // Match: LABEL NUMBERS *VALUE [Rs TOTAL optional]
- const match = line.match(/^(\S+)\s+(.+?)\s+\*([\d.]+)(?:\s*(?:Rs)?\s*(\d+))?/);
+ .map((line) => {
+ const match = line.match(/^(\S+)\s+(.+?)\s+\*([\d.]+)(?:\s*(?:Rs)?\s*(\d+))?/);
if (!match) return null;
-
- const label = match[1].trim();
- const numbersRaw = match[2].trim();
- const value = Number(match[3]);
- const total = match[4] ? Number(match[4]) : (fallbackTotal || 0);
-
+ const label = match[1].trim();
+ const numbersRaw = match[2].trim();
+ const value = Number(match[3]);
+ const total = match[4] ? Number(match[4]) : fallbackTotal || 0;
// If multi-leg ticket, split each part separately
- let numbers: string[] | string[][];
- if (numbersRaw.includes('/')) {
- numbers = numbersRaw
- .split('/')
- .map(part => part.split(',').map(s => s.trim()).filter(Boolean));
- } else {
- numbers = numbersRaw.split(',').map(s => s.trim()).filter(Boolean);
- }
-
+ let numbers: string[] | string[][];
+ if (numbersRaw.includes('/')) {
+ numbers = numbersRaw
+ .split('/')
+ .map((part) => part.split(',').map((s) => s.trim()).filter(Boolean));
+ } else {
+ numbers = numbersRaw.split(',').map((s) => s.trim()).filter(Boolean);
+ }
return {
- label,
- numbers,
- value,
- total,
- isBoxed: numbersRaw.startsWith('#')
+ label,
+ numbers,
+ value,
+ total,
+ isBoxed: numbersRaw.startsWith('#'),
};
})
.filter(Boolean) as SelectionData[];
@@ -183,29 +184,26 @@ parseWinLabelsToRows(winLabels: string, fallbackTotal?: number): SelectionData[]
confirm() {
this.showPrintButton = true; // Show Print button after confirming
console.log('✅ [DEBUG] Ticket confirmed.');
+ this.syncToSecondScreen(); // Sync after confirm
}
-
- //-----------------------REPEAT PRINT LOGIC ----------------------------------
printRepeat() {
console.log('🖨️ [DEBUG] Printing ticket...');
-
- const userName = localStorage.getItem('userName') || 'Unknown';
-
- // Keep currentDate as a Date object
- const now = new Date();
-
- // 🆕 Create Barcode ID (same combo format)
- const day = String(now.getDate()).padStart(2, '0');
- const month = String(now.getMonth() + 1).padStart(2, '0');
- const year = String(now.getFullYear()).slice(-2);
- const timeStr = `${String(now.getHours()).padStart(2, '0')}${String(now.getMinutes()).padStart(2, '0')}${String(now.getSeconds()).padStart(2, '0')}`;
- const millis = String(now.getMilliseconds()).padStart(3, '0');
- const barcodeId = `1111${day}${month}${year}${timeStr}${millis}`;
+ const userName = localStorage.getItem('userName') || 'Unknown';
+ const now = new Date();
+ const day = String(now.getDate()).padStart(2, '0');
+ const month = String(now.getMonth() + 1).padStart(2, '0');
+ const year = String(now.getFullYear()).slice(-2);
+ const timeStr = `${String(now.getHours()).padStart(2, '0')}${String(now.getMinutes()).padStart(
+ 2,
+ '0'
+ )}${String(now.getSeconds()).padStart(2, '0')}`;
+ const millis = String(now.getMilliseconds()).padStart(3, '0');
+ const barcodeId = `1111${day}${month}${year}${timeStr}${millis}`;
const printableRows = this.filledRows
- .filter(row => row.label && row.numbers.length > 0 && row.total > 0)
- .map(row => {
+ .filter((row) => row.label && row.numbers.length > 0 && row.total > 0)
+ .map((row) => {
const horses = Array.isArray(row.numbers) ? row.numbers.join(',') : row.numbers;
return `${row.label.padEnd(6)} ${horses.padEnd(15)} * ${String(row.value).padEnd(3)} ₹${row.total}`;
})
@@ -214,7 +212,6 @@ parseWinLabelsToRows(winLabels: string, fallbackTotal?: number): SelectionData[]
const ticketContent = `
BTC Race Ticket
${printableRows}
-
Barcode ID : ${barcodeId}
Printed by : ${userName}
Date : ${now.toLocaleString()}`;
@@ -224,27 +221,27 @@ Date : ${now.toLocaleString()}`;
// ✅ Send to print server
const payload = {
type: 'repeat',
- printedBy: userName,
- barcodeId, // send barcode separately
+ printedBy: userName,
+ barcodeId,
content: ticketContent,
- timestamp: now.toLocaleString()
+ timestamp: now.toLocaleString(),
};
fetch('http://localhost:9100/print', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(payload)
+ body: JSON.stringify(payload),
})
- .then(response => {
- if (!response.ok) throw new Error(`Printer error: ${response.status}`);
- return response.text();
- })
- .then(result => {
- console.log("✅ Repeat ticket print successful:", result);
- })
- .catch(error => {
- console.error("❌ Repeat ticket print failed:", error);
- });
+ .then((response) => {
+ if (!response.ok) throw new Error(`Printer error: ${response.status}`);
+ return response.text();
+ })
+ .then((result) => {
+ console.log('✅ Repeat ticket print successful:', result);
+ })
+ .catch((error) => {
+ console.error('❌ Repeat ticket print failed:', error);
+ });
// --- Update localStorage for transaction summary like normal print ---
// 1. Increment printClickCount
@@ -258,14 +255,13 @@ Date : ${now.toLocaleString()}`;
const existingTickets = existingTicketsStr ? JSON.parse(existingTicketsStr) : [];
// Calculate totalAmount for this repeat print
const totalAmount = this.filledRows
- .filter(row => row.label && row.numbers.length > 0 && row.total > 0)
+ .filter((row) => row.label && row.numbers.length > 0 && row.total > 0)
.reduce((sum, row) => sum + (row.total || 0), 0);
const ticketEntry = {
type: 'ticket',
printedBy: userName,
totalAmount,
content: ticketContent,
-
};
existingTickets.push(ticketEntry);
localStorage.setItem('localTickets', JSON.stringify(existingTickets));
@@ -276,25 +272,24 @@ Date : ${now.toLocaleString()}`;
// Hide Confirm and Print buttons before clearing selections
this.showConfirmButton = false;
this.showPrintButton = false;
-
- this.erase(); // Clear selections after hiding buttons
-
- // 👉 Recalculate totals after erase to update transaction summary
- this.calculateTotal();
-}
-
+ this.erase();
+ this.syncToSecondScreen(); // Sync after print
+ }
//------------------------------PRINT REPEAT ENDED HERE-----------------------------------------------------S
- erase() {
+ erase() {
this.selectionService.clearSelections();
this.resetSelections();
// 👉 Also recalculate totals after erase to keep summary in sync
this.calculateTotal();
+ this.syncToSecondScreen(); // Sync after erase
}
+
resetSelections() {
// No-op: Prevent error and allow summary to update
// (If you want to reset any local state, do it here)
}
+
ngOnDestroy() {
this.sub1.unsubscribe();
this.sub2.unsubscribe();
diff --git a/btc-UI/src/app/components/shared-display/shared-display.component.html b/btc-UI/src/app/components/shared-display/shared-display.component.html
index 6c3a9f6..ed88d22 100644
--- a/btc-UI/src/app/components/shared-display/shared-display.component.html
+++ b/btc-UI/src/app/components/shared-display/shared-display.component.html
@@ -8,8 +8,11 @@
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/btc-UI/src/app/components/shared-display/shared-display.component.ts b/btc-UI/src/app/components/shared-display/shared-display.component.ts
index ef94141..87cca14 100644
--- a/btc-UI/src/app/components/shared-display/shared-display.component.ts
+++ b/btc-UI/src/app/components/shared-display/shared-display.component.ts
@@ -1,45 +1,84 @@
-
+// shared-display.component.ts
import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
-import { SharedStateService } from '../../service/shared-state.service';
import { CommonModule } from '@angular/common';
+import { SharedStateService } from '../../service/shared-state.service';
import { SharedTableComponent } from '../shared-table/shared-table.component';
+import { SelectionData } from '../selection.service/selection.service';
+import { FormatNumbersPipe } from '../../../format-numbers.pipe';
+
+interface SharedData {
+ filledRows: SelectionData[];
+ summaryRows: { col1: string; col2: number; col3: number }[];
+ grandTotal: number;
+ salesTotal: number;
+ receiveTotal: number;
+ totalClicks: number;
+}
@Component({
selector: 'app-shared-display',
standalone: true,
- imports: [CommonModule, SharedTableComponent],
+ imports: [CommonModule, SharedTableComponent, FormatNumbersPipe],
templateUrl: './shared-display.component.html',
styleUrls: ['./shared-display.component.css'],
})
export class SharedDisplayComponent implements OnInit {
selectedVenue: string = 'Select Venue';
selectedRace: string = '1';
- summaryRows = Array.from({ length: 4 }, () => ({ col1: '', col2: '', col3: '' }));
- rows = Array.from({ length: 5 }, () => ({ col1: '', col2: '', col3: '', col4: '' }));
- totalAmount = '';
+ summaryRows: { col1: string; col2: number; col3: number }[] = [
+ { col1: 'Sales', col2: 0, col3: 0 },
+ { col1: 'Cancel', col2: 0, col3: 0 },
+ { col1: 'Payout', col2: 0, col3: 0 },
+ { col1: 'Receive', col2: 0, col3: 0 },
+ ];
+ filledRows: SelectionData[] = Array.from({ length: 5 }, () => ({
+ label: '',
+ numbers: [],
+ value: 0,
+ total: 0,
+ }));
+ grandTotal: number = 0;
+ salesTotal: number = 0;
+ receiveTotal: number = 0;
+ totalClicks: number = 0;
+
constructor(
private sharedStateService: SharedStateService,
private cdRef: ChangeDetectorRef
) {}
ngOnInit(): void {
+ console.log('[SHARED DISPLAY] Initializing, electronAPI available:', !!window.electronAPI);
+
this.sharedStateService.sharedData$.subscribe((data) => {
console.log('[SHARED DISPLAY] Received shared data:', data);
-
if (!data) return;
-
if (data.type === 'selectedVenue') {
this.selectedVenue = data.value;
console.log('[SHARED DISPLAY] Venue updated to:', this.selectedVenue);
}
-
if (data.type === 'selectedRace') {
this.selectedRace = data.value;
console.log('[SHARED DISPLAY] Race updated to:', this.selectedRace);
}
-
- this.cdRef.detectChanges(); // Force UI update
+ this.cdRef.detectChanges();
});
- }
-}
+ if (window.electronAPI && window.electronAPI.onUpdateSharedData) {
+ window.electronAPI.onUpdateSharedData((data: SharedData) => {
+ console.log('[SHARED DISPLAY] Received IPC data:', data);
+ if (!data) return;
+ this.filledRows = data.filledRows || this.filledRows;
+ this.summaryRows = data.summaryRows || this.summaryRows;
+ this.grandTotal = data.grandTotal || 0;
+ this.salesTotal = data.salesTotal || 0;
+ this.receiveTotal = data.receiveTotal || 0;
+ this.totalClicks = data.totalClicks || 0;
+ console.log('[SHARED DISPLAY] Updated filledRows:', this.filledRows.map(row => ({ ...row, numbers: JSON.stringify(row.numbers) })));
+ this.cdRef.detectChanges();
+ });
+ } else {
+ console.error('[SHARED DISPLAY] electronAPI or onUpdateSharedData not available');
+ }
+ }
+}
\ No newline at end of file
diff --git a/btc-UI/src/app/components/shared-table/shared-table.component.html b/btc-UI/src/app/components/shared-table/shared-table.component.html
index 2dfa105..0f8b5ca 100644
--- a/btc-UI/src/app/components/shared-table/shared-table.component.html
+++ b/btc-UI/src/app/components/shared-table/shared-table.component.html
@@ -1,51 +1,59 @@
+
-
-
-
-
Transaction Summary
+
+
+
+
+
Transaction Summary
+
+
+
+
+
+
+
+
+
+ | {{ row.col1 }} |
+ {{ row.col2 }} |
+ {{ row.col3 }} |
+
+
+
+
+
+
-
-
-
-
- | {{ row.col1 }} |
- {{ row.col2 }} |
- {{ row.col3 }} |
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+ | {{ row.label }} |
+
+ {{ row.isBoxed ? '# ' : '' }}{{ $any(row.numbers) | formatNumbers }}
+ |
+ {{ row.value || '' }} |
+ {{ row.total || '' }} |
+
+
+
+
+
+
Amount : ₹ {{ totalAmount }}
+
-
-
-
-
-
- | {{ row.col1 }} |
- {{ row.col2 }} |
- {{ row.col3 }} |
- {{ row.col4 }} |
-
-
-
-
-
-
Amount : {{ totalAmount }}
-
-
-
-
-
-
-
-
+
diff --git a/btc-UI/src/app/components/shared-table/shared-table.component.ts b/btc-UI/src/app/components/shared-table/shared-table.component.ts
index 7cad543..19506b0 100644
--- a/btc-UI/src/app/components/shared-table/shared-table.component.ts
+++ b/btc-UI/src/app/components/shared-table/shared-table.component.ts
@@ -1,22 +1,20 @@
-import { Component, Input } from '@angular/core';
+// shared-table.component.ts
+import { Component, Input, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
-import { WebsocketService } from '../../service/websocket.service'; // adjust path if needed
+import { SelectionData } from '../selection.service/selection.service';
+import { FormatNumbersPipe } from '../../../format-numbers.pipe';
+import { WebsocketService } from '../../service/websocket.service'; // Adjust path as needed
@Component({
selector: 'app-shared-table',
standalone: true,
- imports: [CommonModule],
+ imports: [CommonModule, FormatNumbersPipe],
templateUrl: './shared-table.component.html',
- styleUrls: ['./shared-table.component.css']
+ styleUrls: ['./shared-table.component.css'],
})
-// export class SharedTableComponent {
-// @Input() summaryRows: any[] = [];
-// @Input() rows: any[] = [];
-// @Input() totalAmount: string = '';
-// }
-export class SharedTableComponent {
- @Input() summaryRows: any[] = [];
- @Input() rows: any[] = [];
+export class SharedTableComponent implements OnInit {
+ @Input() summaryRows: { col1: string; col2: number; col3: number }[] = [];
+ @Input() rows: SelectionData[] = [];
@Input() totalAmount: string = '';
message = '';
@@ -25,12 +23,14 @@ export class SharedTableComponent {
constructor(private websocketService: WebsocketService) {}
ngOnInit() {
- this.websocketService.message$.subscribe(msg => {
+ this.websocketService.message$.subscribe((msg) => {
this.message = msg;
+ console.log('[SHARED TABLE] WebSocket message:', msg);
});
- this.websocketService.isConnected$.subscribe(status => {
+ this.websocketService.isConnected$.subscribe((status) => {
this.isConnected = status;
+ console.log('[SHARED TABLE] WebSocket connection status:', status);
});
}
-}
+}
\ No newline at end of file
diff --git a/btc-UI/src/electron.d.ts b/btc-UI/src/electron.d.ts
new file mode 100644
index 0000000..36ebac7
--- /dev/null
+++ b/btc-UI/src/electron.d.ts
@@ -0,0 +1,21 @@
+// src/electron.d.ts
+interface ElectronAPI {
+ openSecondScreen: () => void;
+ closeSecondScreen: () => void;
+ getBtid: () => Promise
;
+ syncSharedData: (data: SharedData) => void;
+ onUpdateSharedData: (callback: (data: SharedData) => void) => void;
+}
+
+interface SharedData {
+ filledRows: SelectionData[];
+ summaryRows: { col1: string; col2: number; col3: number }[];
+ grandTotal: number;
+ salesTotal: number;
+ receiveTotal: number;
+ totalClicks: number;
+}
+
+interface Window {
+ electronAPI: ElectronAPI;
+}
\ No newline at end of file
diff --git a/btc-UI/src/format-numbers.pipe.ts b/btc-UI/src/format-numbers.pipe.ts
new file mode 100644
index 0000000..ae99dde
--- /dev/null
+++ b/btc-UI/src/format-numbers.pipe.ts
@@ -0,0 +1,15 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'formatNumbers',
+ standalone: true,
+})
+export class FormatNumbersPipe implements PipeTransform {
+ transform(values: (string | number)[]): string {
+ if (!values || !Array.isArray(values)) {
+ return '';
+ }
+
+ return values.map((val) => val.toString()).join(',');
+ }
+}