133 lines
3.5 KiB
TypeScript
133 lines
3.5 KiB
TypeScript
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
|
|
import { getSSEConnection, setupSSECleanup, SSEClient } from 'sse-client';
|
|
|
|
// Set up SSE cleanup once at the application level
|
|
setupSSECleanup();
|
|
|
|
// Define the order state type
|
|
interface OrderState {
|
|
orderId: string;
|
|
orderStatus: number;
|
|
preparationState: {
|
|
utcStarted: string;
|
|
utcEnded: string | null;
|
|
};
|
|
deliveryState: {
|
|
utcStarted: string | null;
|
|
utcEnded: string | null;
|
|
};
|
|
// Add other properties as needed
|
|
}
|
|
|
|
// Define the order state changed message type
|
|
interface OrderStateChangedMessage {
|
|
messageType: string;
|
|
orderId: string;
|
|
prevState: OrderState;
|
|
currentState: OrderState;
|
|
}
|
|
|
|
@Component({
|
|
selector: 'app-order-tracker',
|
|
template: `
|
|
<div class="order-tracker">
|
|
<div *ngIf="error" class="error">{{ error }}</div>
|
|
<div *ngIf="!orderState" class="loading">Loading order status...</div>
|
|
<div *ngIf="orderState">
|
|
<h2>Order #{{ orderState.orderId }}</h2>
|
|
<div class="order-status">
|
|
Status: {{ getStatusText(orderState.orderStatus) }}
|
|
</div>
|
|
<!-- Render other order details -->
|
|
</div>
|
|
</div>
|
|
`,
|
|
styles: [`
|
|
.order-tracker {
|
|
padding: 1rem;
|
|
border: 1px solid #eee;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.error {
|
|
color: red;
|
|
}
|
|
|
|
.loading {
|
|
color: #888;
|
|
}
|
|
`]
|
|
})
|
|
export class OrderTrackerComponent implements OnInit, OnDestroy {
|
|
@Input() orderId!: string;
|
|
@Input() authToken!: string;
|
|
|
|
orderState: OrderState | null = null;
|
|
error: string | null = null;
|
|
private client: SSEClient | null = null;
|
|
|
|
ngOnInit(): void {
|
|
// API base URL
|
|
const apiBaseUrl = 'https://api.example.com';
|
|
|
|
// SSE URL
|
|
const sseUrl = `${apiBaseUrl}/events/orders/${this.orderId}`;
|
|
|
|
// Get or create a connection for this order
|
|
this.client = getSSEConnection(sseUrl, `order-${this.orderId}`, {
|
|
headers: {
|
|
'X-Signed-Auth': this.authToken
|
|
},
|
|
debug: true
|
|
});
|
|
|
|
// Listen for order state changes
|
|
this.client.on('orderStateChanged', (event: any) => {
|
|
try {
|
|
const data = event.parsedData as OrderStateChangedMessage;
|
|
console.log('Order state changed:', data);
|
|
|
|
// Update state with new order state
|
|
this.orderState = data.currentState;
|
|
|
|
// If order is ended, close the connection
|
|
if (data.currentState && data.currentState.orderStatus === 1111) {
|
|
console.log(`Order ${this.orderId} ended, closing SSE connection`);
|
|
this.client?.close();
|
|
}
|
|
} catch (err) {
|
|
this.error = 'Error parsing order state data';
|
|
console.error('Error parsing order state data:', err);
|
|
}
|
|
});
|
|
|
|
// Listen for connection errors
|
|
this.client.on('error', (event: any) => {
|
|
this.error = 'SSE connection error';
|
|
console.error('SSE connection error:', event.detail);
|
|
});
|
|
}
|
|
|
|
ngOnDestroy(): void {
|
|
// Clean up on destroy
|
|
if (this.client) {
|
|
this.client.close();
|
|
this.client = null;
|
|
}
|
|
}
|
|
|
|
// Helper function to get status text from status code
|
|
getStatusText(status: number): string {
|
|
switch (status) {
|
|
case 0: return 'Created';
|
|
case 10: return 'Accepted';
|
|
case 20: return 'Preparing';
|
|
case 30: return 'Ready for Pickup';
|
|
case 40: return 'Out for Delivery';
|
|
case 50: return 'Delivered';
|
|
case 1111: return 'Completed';
|
|
default: return `Unknown (${status})`;
|
|
}
|
|
}
|
|
}
|