import { io, Socket } from 'socket.io-client'; const BASE_URL = 'https://2dbb-202-8-116-13.ngrok-free.app'; const SOCKET_URL = `${BASE_URL}/tracking`; export interface DriverLocationUpdate { orderId: string; latitude: number; longitude: number; heading?: number; speedKph?: number; recordedAt: string; } export interface TrackingStatusUpdate { orderId: string; status: 'OUT_FOR_DELIVERY' | 'DELIVERED'; timestamp: string; } class SocketService { private socket: Socket | null = null; connect(token: string): Socket { if (this.socket?.connected) { console.log( '[Socket] Already connected to Tracking Namespace', this.socket, ); return this.socket; } this.socket = io(SOCKET_URL, { auth: { token }, transports: ['websocket'], reconnection: true, reconnectionAttempts: Infinity, reconnectionDelay: 2000, }); this.socket.on('connect', () => { console.log('[Socket] Connected to Tracking Namespace'); }); this.socket.on('connect_error', error => { console.error('[Socket] Connection Error:', error.message); }); this.socket.on('disconnect', reason => { console.log('[Socket] Disconnected from Tracking Namespace:', reason); }); return this.socket; } joinOrderTracking(orderId: string) { this.socket?.emit('join_order_tracking', { orderId }); console.log(`[Socket] Emitted join_order_tracking for order: ${orderId}`); } leaveOrderTracking(orderId: string) { this.socket?.emit('leave_order_tracking', { orderId }); console.log(`[Socket] Emitted leave_order_tracking for order: ${orderId}`); } onDriverLocationUpdate(callback: (data: DriverLocationUpdate) => void) { console.log(callback); this.socket?.on('driver_location_update', callback); } onOrderStatusUpdate(callback: (data: TrackingStatusUpdate) => void) { this.socket?.on('order_tracking_status', callback); } disconnect(orderId?: string) { if (this.socket) { if (orderId) { this.leaveOrderTracking(orderId); } this.socket.off('driver_location_update'); this.socket.off('order_tracking_status'); this.socket.disconnect(); this.socket = null; console.log('[Socket] Disconnected manually'); } } get connected(): boolean { return this.socket?.connected ?? false; } } export const socketService = new SocketService(); export default socketService;