feat: Add core queue management system with Pinia store, WebSocket integration, and dedicated pages for patient check-in and kiosk display.
This commit is contained in:
No files matched your search
+46
-16
@@ -1,9 +1,9 @@
|
||||
// composables/useWebSocket.ts
|
||||
import { ref, computed, onUnmounted, getCurrentInstance } from 'vue'
|
||||
import { ref, computed, onUnmounted, getCurrentInstance, toValue } from 'vue'
|
||||
|
||||
export interface WebSocketConfig {
|
||||
url: string
|
||||
clientId: string
|
||||
url: string | any
|
||||
clientId: string | any
|
||||
onMessage?: (data: any) => void
|
||||
onOpen?: () => void
|
||||
onClose?: () => void
|
||||
@@ -24,8 +24,11 @@ export const useWebSocket = (config: WebSocketConfig) => {
|
||||
const reconnectAttempts = ref(0)
|
||||
const reconnectTimer = ref<NodeJS.Timeout | null>(null)
|
||||
|
||||
const currentUrl = computed(() => toValue(config.url))
|
||||
const currentClientId = computed(() => toValue(config.clientId))
|
||||
|
||||
const wsUrl = computed(() => {
|
||||
let baseUrl = config.url
|
||||
let baseUrl = currentUrl.value
|
||||
|
||||
// Automatically upgrade to secure protocols if caller uses HTTPS
|
||||
if (typeof window !== 'undefined' && window.location.protocol === 'https:') {
|
||||
@@ -37,21 +40,44 @@ export const useWebSocket = (config: WebSocketConfig) => {
|
||||
}
|
||||
|
||||
const url = new URL(baseUrl)
|
||||
url.searchParams.set('client_id', config.clientId)
|
||||
url.searchParams.set('client_id', currentClientId.value)
|
||||
return url.toString()
|
||||
})
|
||||
|
||||
const clearHandlers = (wsInstance: WebSocket | null) => {
|
||||
if (wsInstance) {
|
||||
wsInstance.onopen = null
|
||||
wsInstance.onmessage = null
|
||||
wsInstance.onclose = null
|
||||
wsInstance.onerror = null
|
||||
}
|
||||
}
|
||||
|
||||
const connect = () => {
|
||||
try {
|
||||
// Close existing connection if any
|
||||
if (ws.value && ws.value.readyState !== WebSocket.CLOSED) {
|
||||
ws.value.close()
|
||||
// Clear any pending reconnect timer first
|
||||
if (reconnectTimer.value) {
|
||||
clearTimeout(reconnectTimer.value)
|
||||
reconnectTimer.value = null
|
||||
}
|
||||
|
||||
ws.value = new WebSocket(wsUrl.value)
|
||||
// Close existing connection if any, and CLEAN HANDLERS to prevent recursion
|
||||
if (ws.value) {
|
||||
if (ws.value.readyState !== WebSocket.CLOSED) {
|
||||
console.log('🔌 Closing existing WebSocket before new connection...')
|
||||
clearHandlers(ws.value)
|
||||
ws.value.close()
|
||||
}
|
||||
ws.value = null
|
||||
}
|
||||
|
||||
const connectionUrl = wsUrl.value
|
||||
console.log('🔌 Connecting to WebSocket:', connectionUrl)
|
||||
|
||||
ws.value = new WebSocket(connectionUrl)
|
||||
|
||||
ws.value.onopen = () => {
|
||||
console.log('WebSocket connected:', config.clientId)
|
||||
console.log('✅ WebSocket connected:', currentClientId.value)
|
||||
isConnected.value = true
|
||||
reconnectAttempts.value = 0
|
||||
config.onOpen?.()
|
||||
@@ -67,16 +93,17 @@ export const useWebSocket = (config: WebSocketConfig) => {
|
||||
}
|
||||
|
||||
ws.value.onclose = () => {
|
||||
console.log('WebSocket closed:', config.clientId)
|
||||
console.log('❌ WebSocket closed:', currentClientId.value)
|
||||
isConnected.value = false
|
||||
config.onClose?.()
|
||||
|
||||
// Attempt to reconnect
|
||||
// Attempt to reconnect only if we didn't just reach max attempts
|
||||
// The reconnectTimer is cleared in disconnect() and at start of connect()
|
||||
if (reconnectAttempts.value < (config.maxReconnectAttempts || 5)) {
|
||||
reconnectAttempts.value++
|
||||
const interval = config.reconnectInterval || 3000
|
||||
console.log(`⏳ Reconnecting in ${interval}ms... Attempt ${reconnectAttempts.value}`)
|
||||
reconnectTimer.value = setTimeout(() => {
|
||||
console.log(`Reconnecting... Attempt ${reconnectAttempts.value}`)
|
||||
connect()
|
||||
}, interval)
|
||||
} else {
|
||||
@@ -85,11 +112,11 @@ export const useWebSocket = (config: WebSocketConfig) => {
|
||||
}
|
||||
|
||||
ws.value.onerror = (error) => {
|
||||
console.error('WebSocket error:', error)
|
||||
console.error('⚠️ WebSocket error:', error)
|
||||
config.onError?.(error)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error creating WebSocket:', error)
|
||||
console.error('❌ Error creating WebSocket:', error)
|
||||
config.onError?.(error as Event)
|
||||
}
|
||||
}
|
||||
@@ -100,10 +127,13 @@ export const useWebSocket = (config: WebSocketConfig) => {
|
||||
reconnectTimer.value = null
|
||||
}
|
||||
if (ws.value) {
|
||||
console.log('🔌 Manual disconnect: Cleaning handlers and closing...')
|
||||
clearHandlers(ws.value)
|
||||
ws.value.close()
|
||||
ws.value = null
|
||||
}
|
||||
isConnected.value = false
|
||||
reconnectAttempts.value = 0
|
||||
}
|
||||
|
||||
const sendMessage = (message: any) => {
|
||||
@@ -125,7 +155,7 @@ export const useWebSocket = (config: WebSocketConfig) => {
|
||||
postUrl = config.fallbackPostUrl
|
||||
} else {
|
||||
// Derive post URL from WebSocket URL (legacy behavior)
|
||||
let baseUrl = config.url
|
||||
let baseUrl = currentUrl.value
|
||||
if (baseUrl.startsWith('ws://')) {
|
||||
baseUrl = baseUrl.replace('ws://', 'http://')
|
||||
} else if (baseUrl.startsWith('wss://')) {
|
||||
|
||||
Reference in New Issue
Block a user