149 lines
3.6 KiB
Vue
149 lines
3.6 KiB
Vue
<template>
|
|
<div class="order-tracker">
|
|
<div v-if="error" class="error">{{ error }}</div>
|
|
<div v-else-if="!orderState" class="loading">Loading order status...</div>
|
|
<div v-else>
|
|
<h2>Order #{{ orderState.orderId }}</h2>
|
|
<div class="order-status">
|
|
Status: {{ getStatusText(orderState.orderStatus) }}
|
|
</div>
|
|
<!-- Render other order details -->
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { defineComponent, ref, onMounted, onUnmounted } from 'vue';
|
|
import { getSSEConnection, setupSSECleanup } 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;
|
|
}
|
|
|
|
export default defineComponent({
|
|
name: 'OrderTracker',
|
|
props: {
|
|
orderId: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
authToken: {
|
|
type: String,
|
|
required: true
|
|
}
|
|
},
|
|
setup(props) {
|
|
const orderState = ref<OrderState | null>(null);
|
|
const error = ref<string | null>(null);
|
|
let client: any = null;
|
|
|
|
onMounted(() => {
|
|
// API base URL
|
|
const apiBaseUrl = 'https://api.example.com';
|
|
|
|
// SSE URL
|
|
const sseUrl = `${apiBaseUrl}/events/orders/${props.orderId}`;
|
|
|
|
// Get or create a connection for this order
|
|
client = getSSEConnection(sseUrl, `order-${props.orderId}`, {
|
|
headers: {
|
|
'X-Signed-Auth': props.authToken
|
|
},
|
|
debug: true
|
|
});
|
|
|
|
// Listen for order state changes
|
|
client.on('orderStateChanged', (event: any) => {
|
|
try {
|
|
const data = event.parsedData as OrderStateChangedMessage;
|
|
console.log('Order state changed:', data);
|
|
|
|
// Update state with new order state
|
|
orderState.value = data.currentState;
|
|
|
|
// If order is ended, close the connection
|
|
if (data.currentState && data.currentState.orderStatus === 1111) {
|
|
console.log(`Order ${props.orderId} ended, closing SSE connection`);
|
|
client.close();
|
|
}
|
|
} catch (err) {
|
|
error.value = 'Error parsing order state data';
|
|
console.error('Error parsing order state data:', err);
|
|
}
|
|
});
|
|
|
|
// Listen for connection errors
|
|
client.on('error', (event: any) => {
|
|
error.value = 'SSE connection error';
|
|
console.error('SSE connection error:', event.detail);
|
|
});
|
|
});
|
|
|
|
onUnmounted(() => {
|
|
// Clean up on unmount
|
|
if (client) {
|
|
client.close();
|
|
}
|
|
});
|
|
|
|
// Helper function to get status text from status code
|
|
const 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})`;
|
|
}
|
|
};
|
|
|
|
return {
|
|
orderState,
|
|
error,
|
|
getStatusText
|
|
};
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
.order-tracker {
|
|
padding: 1rem;
|
|
border: 1px solid #eee;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.error {
|
|
color: red;
|
|
}
|
|
|
|
.loading {
|
|
color: #888;
|
|
}
|
|
</style>
|