4.2 KiB
CLAUDE.md — src/pages/nearle/orders/
Rules for editing orders.js, OrdersPreview.js, createorder1.js, newcreateOrder.js, multipleOrders.js, details.js, and the optimised preview.
This is the revenue-critical area of the console — the path from "order received" to "rider assigned" runs through here. The optimiser hand-off and the assign-and-notify sequence are the two flows you must not break.
1. The three dispatch modes (Mode 0 / 1 / 2)
The orders page tracks the chosen mode in aiModeRef (a useRef, not state — it's set just before the mutation fires).
| Mode | Solver | Endpoint | When operator picks it |
|---|---|---|---|
| 0 · Manual | routes.workolik.com |
POST /optimization/createdeliveries |
"Optimise selected orders" — gives a tentative route, operator can rearrange in preview |
| 1 · Bike | routes.workolik.com |
POST /optimization/riderassign?hypertuning_params={...} |
Bike fleet with hyper-tuning (Balanced / Fuel Saver / Aggressive / Strict Zone) |
| 2 · Auto | routemate.workolik.com |
POST /optimization/riderassign?strategy=multi_trip |
Auto-rickshaw fleet, hourly multi-trip |
The mutation function gets picked by mode:
useMutation({
mutationFn: aiModeRef.current == 0 ? createOptimisationDeliveries : createAutomationDeliveries,
...
});
createAutomationDeliveries covers both Mode 1 and Mode 2 — the difference is the URL it constructs and the hypertuning_params query string. Don't split them into separate functions.
2. The hand-off to /orders/preview (and then /dispatch/preview)
After the solver returns:
- Solver response → stored in the orders page state.
- Operator navigates to
OrdersPreview.js(/doormile/orders/preview) for a first look. - From there →
/doormile/dispatch/preview(Preview.jsin the dispatch folder) for drag-and-drop adjustment. Preview.jsis the one that callsfinalCreatedeliveriesto commit.
Don't try to commit from orders.js or OrdersPreview.js — they are read-only / staging steps. The reconcile-then-commit dance only happens on the dispatch preview page (see src/pages/nearle/dispatch/CLAUDE.md).
3. Selection state
Multi-order optimisation uses a checkbox column. The selection lives in component state as an array of order objects (not just IDs) because the solver payload needs full order data (pickup_lat, pickup_lng, drop_lat, drop_lng, weight, expecteddeliverytime, etc.).
- "Select all" is implemented per visible page — not across all loaded infinite pages — to avoid accidental multi-thousand-order solver runs.
- Selection clears when
currentStatus,appId, or date range changes. This is intentional — solver runs are scoped to a single tab. - Don't add a "select across pages" affordance without confirming the optimiser's payload limits.
4. Cancellation paths
| Function | Use |
|---|---|
cancelOrder (PUT /orders/updateorder) |
Single-order cancel (per-row icon) |
cancelMultipleOrder (PUT /orders/updatemultipleorders) |
Bulk cancel of selected orders (toolbar button) |
Both record a cancel timestamp on the order. Neither triggers a rider FCM notification because the order was never assigned. Do not call notifyRider after these.
5. Filters & data
The orders list is a useInfiniteQuery keyed by ['fetchorders', appId, currentStatus, debouncedSearch, startdate, enddate, rowsPerPage, tenantid, locationid]. The corresponding api.js function (fetchOrders) destructures in this same order — see src/pages/api/CLAUDE.md §1.
The summary endpoint (fetchorderscount) uses a slightly different key — currentStatus comes after the date range. Match the call site, don't normalise.
6. Don'ts specific to this folder
- Don't introduce a 4th dispatch mode without coordinating with the workolik backend team. The solver URL and
?hypertuning_params=query are versioned. - Don't move solver URLs into env vars. They are deliberately hardcoded because the optimiser is a separate, versioned service — pinning the URL is the version pin.
- Don't fold
createorder1.js,newcreateOrder.js, andmultipleOrders.jsinto one component. They serve different operator flows (existing customer vs new customer vs CSV bulk import).