# CLAUDE.md — `src/pages/api/`

Rules for editing `api.js`. This is the **central API layer** — every page calls into it. The root `CLAUDE.md` covers project-wide conventions; this file is the scoped rule sheet for the API layer specifically.

---

## 1. Function signature patterns

### TanStack `useQuery` / `useInfiniteQuery` consumers
Destructure from `queryKey` in the order the call site declared it. The leading `_` is the query name and is intentionally discarded.

```js
// Plain query — destructure { queryKey }, skip the [0] name slot
export const fetchorderscount = async ({ queryKey }) => {
  const [, appId, startdate, enddate, currentStatus, tenantid, locationid] = queryKey;
  const url = `${process.env.REACT_APP_URL}/orders/getordersummary/?applocationid=${appId}&...`;
  const response = await axios.get(url);
  return response.data.details;
};

// Infinite query — also receives pageParam (default to 1)
export const fetchOrders = async ({ pageParam = 1, queryKey }) => {
  const [, appId, currentStatus, debouncedSearch, startdate, enddate, rowsPerPage, tenantid, locationid] = queryKey;
  const url = `${process.env.REACT_APP_URL}/orders/tenant/getorders/?applocationid=${appId}&...&pageno=${pageParam}&pagesize=${rowsPerPage}`;
  const response = await axios.get(url);
  return {
    rows: response.data.details,
    nextPage: response.data.details.length === Number(rowsPerPage) ? pageParam + 1 : undefined
  };
};
```

**Hard rules:**
- The query-key array order at the call site MUST match the destructure order here. Re-ordering one without the other silently breaks every caller.
- Infinite queries return `{ rows, nextPage }`. `nextPage` is `undefined` when the page size wasn't filled (signals end-of-stream to `getNextPageParam`).
- Some legacy functions return `{ data, nextPage }` instead of `{ rows, nextPage }` (e.g. `getallcustomers`). Match the existing shape rather than "fixing" it — call sites depend on the field name.

---

## 2. Direct positional-argument calls
A few functions take plain positional arguments instead of `queryKey` — usually when they're invoked from a `useMutation` or imperatively. Example: `getTenants(appId)`, `gettenantlocations(tenantid)`.

Pick the signature based on how the function is called:
- Called via `useQuery({ queryFn: fn })` → destructure `{ queryKey }`.
- Called via `useQuery({ queryFn: () => fn(arg) })` → take positional args.
- Called from a mutation or imperatively → take positional args.

---

## 3. Base URL selection

| Use base | When |
|---|---|
| `process.env.REACT_APP_URL` | Default for ~95% of endpoints |
| `process.env.REACT_APP_URL2` | `/users/update`, `/tenants/update`, `/tenants/update/services`, archival `/orders/getorders`, `/partners/getriderlogs` |
| Hardcoded `https://routes.workolik.com` | Bike solver + reconcile-steps + batch efficiency |
| Hardcoded `https://routemate.workolik.com` | Auto / multi-trip solver |
| Hardcoded `https://jupiter.nearle.app` | Login + final `/deliveries/createdeliveries` commit |

When adding a new endpoint, check whether the backend actually serves it on URL or URL2 — don't guess. URL2 lives on a separate service.

---

## 4. Error handling pattern

```js
try {
  const response = await axios.get(`${process.env.REACT_APP_URL}/...`);
  return response.data.details;   // or .summary, .data, etc — depends on backend shape
} catch (err) {
  const message = err.response?.data?.message || err.message || 'Something went wrong';
  OpenToast(message);
  return null;                    // or return [] / {} — match what the caller expects
}
```

- Toast on failure via `OpenToast` from `components/third-party/OpenToast`. Don't `throw` — TanStack Query's `onError` is rarely wired by callers.
- Return a sensible empty default (`null`, `[]`, `{}`) so the call site's destructuring doesn't crash.
- Don't `console.log(err)` AND toast — toast is enough. Some legacy functions do both; new functions should not.

---

## 5. When NOT to add to `api.js`

The user has tolerated a number of pages making direct inline `axios.put` / `axios.post` calls for mutations (e.g. `Tenants.js` calls `axios.put('/tenants/update')` inline). Match the surrounding file:

- **Adding a new shared GET** → put it in `api.js`.
- **Adding a one-off mutation used in only one page** → tolerated inline in that page; doesn't need a new export here.
- **Adding a polling endpoint used by multiple pages** → put it here as a named export so the query cache keys are coherent.

---

## 6. Response shape quirks

Backend response shapes are inconsistent. Don't assume `response.data.details` — check what the specific endpoint returns:

| Backend field | Used by |
|---|---|
| `response.data.details` | Most list endpoints |
| `response.data.summary` | `getcustomersummary`, `gettenantsummary`, `getpricinglist` summary calls |
| `response.data.data` | `getRiderPeriodicLogs`, `getallcustomers` infinite-query page payload |
| `response.data.message` | Mutation success messages (for toast) |
| `response.data.status` | Boolean success flag — check before reading `.details` on some endpoints |

When unsure, log the response once during dev and pick the matching field.

---

## 7. Things that look broken but are intentional

- `const userid = localStorage.getItem('userid');` at module top — read once at module load, intentional for the `fetchAppLocations` helper. Don't move it inside the function.
- Some functions take a `pageno` 0-indexed and others 1-indexed (`pageno: pageParam + 1` vs `pageno: pageParam`). Backend inconsistency — leave it alone unless you confirm the backend side.
- A few legacy commented-out function bodies are kept above their current implementation as historical reference. Don't delete them in a drive-by edit.
