Rooms and Live Order Status

Client Side

storefront/lib/order-socket.ts (the Next.js app, see the Next.js material)

import { io } from 'socket.io-client';

export function trackOrder(orderId: string, token: string, onStatus: (s: { status: string; etaMinutes?: number }) => void) {
  const socket = io('https://api.shopease.in/orders', { auth: { token } });
  socket.on('connect', () => socket.emit('order:track', { orderId }));
  socket.on('order:status', onStatus);
  return () => socket.disconnect();
}

Example

What the customer sees as the order moves:

# server: ordersGateway.emitStatus(...) called by OrdersService

Example output

order:status {"orderId":"ORD-7781","status":"CONFIRMED"}
order:status {"orderId":"ORD-7781","status":"PACKED"}
order:status {"orderId":"ORD-7781","status":"OUT_FOR_DELIVERY","etaMinutes":18}
order:status {"orderId":"ORD-7781","status":"DELIVERED"}

Rooms Explained

Example

A room is a named group of connections; emitting to a room reaches only its members. A model with node:events:

import { EventEmitter } from 'node:events';

class Socket extends EventEmitter {
  rooms = new Set<string>();
  constructor(readonly id: string) { super(); }
}

class Server {
  private sockets: Socket[] = [];
  connect(id: string) {
    const s = new Socket(id);
    this.sockets.push(s);
    s.on('order:status', (data) => console.log('  ' + id + ' got', JSON.stringify(data)));
    return s;
  }
  to(room: string) {
    return {
      emit: (event: string, data: unknown) =>
        this.sockets.filter((s) => s.rooms.has(room)).forEach((s) => s.emit(event, data)),
    };
  }
}

const server = new Server();
const asha = server.connect('asha-phone');
const ashaWeb = server.connect('asha-laptop');
const ravi = server.connect('ravi-phone');
asha.rooms.add('order:ORD-7781');
ashaWeb.rooms.add('order:ORD-7781');
ravi.rooms.add('order:ORD-7790');

console.log('emit PACKED to order:ORD-7781');
server.to('order:ORD-7781').emit('order:status', { orderId: 'ORD-7781', status: 'PACKED' });
console.log('emit OUT_FOR_DELIVERY to order:ORD-7790');
server.to('order:ORD-7790').emit('order:status', { orderId: 'ORD-7790', status: 'OUT_FOR_DELIVERY' });

Output

emit PACKED to order:ORD-7781
  asha-phone got {"orderId":"ORD-7781","status":"PACKED"}
  asha-laptop got {"orderId":"ORD-7781","status":"PACKED"}
emit OUT_FOR_DELIVERY to order:ORD-7790
  ravi-phone got {"orderId":"ORD-7790","status":"OUT_FOR_DELIVERY"}