Skip to content

bug: hold table doesn't set table status to occupied server-side #32

Description

@khaira777

Description

When a user clicks "Hold Table" in the table picker, the order is saved to localStorage (Zustand held-orders store) and the cart is cleared, but no API call is made to set the table status to occupied. The table remains available in the database.

Code Location

frontend/src/app/(dashboard)/pos/page.tsx:274-284:

const handleHoldTable = (tableId: string) => {
  if (cart.items.length === 0) {
    toast.error('Cart is empty');
    return;
  }
  const tableName = tables.find((t) => t.id === tableId)?.name || tableId;
  heldOrders.holdOrder(tableId, cart.items, cart.customerId, cart.guestCount, cart.orderNotes);
  cart.clearCart();
  setShowTablePicker(false);
  toast.success(`Order held for ${tableName}`);
  // ❌ No API call to PATCH /tables/:id/status to 'occupied'
};

The backend already has PATCH /tables/:id/status (main/routes/tables.ts:142-169) that accepts occupied as a valid status.

Impact

  • Two held orders on same table: User holds order for Table 5, opens new cart, holds another order for Table 5 → two held orders exist, table still shows as "available"
  • Multi-device: If FloCafe supports multiple terminals, Device B won't know Table 5 has a held order
  • Data loss: Clear browser data = held orders gone, but table was never marked occupied
  • Race condition: Between holding and restoring, another user could start a new order on the same table

Expected Behavior

When holding an order for a table, the frontend should call PATCH /tables/:id/status with { status: 'occupied' } to mark the table as occupied in the database. When the held order is restored or completed, the status should revert to available (or cleaning if the order was completed).

Suggested Fix

const handleHoldTable = async (tableId: string) => {
  if (cart.items.length === 0) {
    toast.error('Cart is empty');
    return;
  }
  const tableName = tables.find((t) => t.id === tableId)?.name || tableId;
  
  // Mark table as occupied
  await api.patch(`/tables/${tableId}/status`, { status: 'occupied' });
  
  heldOrders.holdOrder(tableId, cart.items, cart.customerId, cart.guestCount, cart.orderNotes);
  cart.clearCart();
  setShowTablePicker(false);
  refreshTables(); // refresh to show updated status
  toast.success(`Order held for ${tableName}`);
};

The reverse (restoring a held order) should also update status back to available.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:backendBackend (Express/SQLite)area:frontendFrontend (React/Next.js)bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions