Commit Graph

98 Commits

Author SHA1 Message Date
f91044e61a ui 2026-10-08 16:57:16 +05:30
8960fb8ebb delivery slot ui 2026-10-08 15:09:36 +05:30
262b83ffbc delivery slot updated in orders and deliveries fix 2026-10-08 11:06:55 +05:30
d24df891fb delivery slot updated on orders and deliveries 2026-10-06 19:40:42 +05:30
56e8a95c6a delivery slot creation 2026-10-06 17:37:02 +05:30
990dd0dc23 toggle update 2026-10-06 12:20:13 +05:30
a764df225f toggle update 2026-10-06 10:34:48 +05:30
b7f9a6aaeb my stock update page ui 2026-10-05 19:20:08 +05:30
bcb5d1de28 health score toggle ui 2026-10-05 17:05:51 +05:30
7f2110d51e health score toggle in same drawer 2026-10-05 13:05:27 +05:30
1eea29cf23 health score toggle 2026-10-05 12:03:35 +05:30
0a828fbe4f health score: move the non-food early return past the hook
`if (!isEdible(category)) return null` sat on the line above `useQuery`, which
made the hook conditional. React counts hooks per component instance, so one
drawer reused for two products -- a soap and then a biscuit, which is ordinary
browsing in the global catalogue -- went 0 hooks then 1 and threw "rendered more
hooks than during the previous render".

That does not degrade the panel, it unmounts the tree: the health score then
disappears for EVERY product until the page is reloaded, which reads exactly
like the feature having been switched off.

The guard now sits after the hook, and `enabled` carries the intent the early
return was protecting -- a non-food product still asks the service nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-30 12:23:50 +05:30
12617b5d81 nutrition panel removed 2026-09-30 11:53:35 +05:30
b73f050669 nutrition 2026-09-29 17:30:18 +05:30
e3fc144d05 auto mail generation 2026-09-29 16:48:10 +05:30
9a991fe5ab cod fix 2026-09-28 19:35:16 +05:30
eeef8851e4 domain change 2026-09-28 18:08:55 +05:30
c9616edad9 seperation of nearle admin 2026-09-28 15:43:07 +05:30
21818320a0 shift fix 2026-09-25 16:19:51 +05:30
9314771aa8 deploy fix 2026-09-25 15:26:23 +05:30
d169d24934 ui fix 2026-09-25 15:21:02 +05:30
3d404665ab rider partner 2026-09-24 19:06:12 +05:30
2f0836df30 status 2026-09-24 16:30:02 +05:30
aca6344cc9 shift 2026-09-24 15:52:27 +05:30
34c68034de phase 0 and 1 2026-09-23 11:36:10 +05:30
cca3c50a89 rider status 2026-09-22 11:13:15 +05:30
19ed3585ff ui/ux on catalogue 2026-09-19 11:25:41 +05:30
93735e232a ui/ux on catalogue 2026-09-18 19:19:34 +05:30
041dc37861 ui/ux improvement 2026-09-18 16:57:24 +05:30
115a06a02c ui improvement 2026-09-17 17:57:21 +05:30
2cd048e6f0 partner 2026-09-17 11:03:57 +05:30
f25b3fcf65 e2e changes 2026-09-16 17:12:30 +05:30
5cb9872037 type check 2026-09-16 11:43:26 +05:30
98398894a5 design 2026-09-15 20:51:01 +05:30
b2104d21b0 fix the four typecheck errors that broke the build
`npm run build` runs `tsc --noEmit` first, so all four stopped the deploy
before vite ever ran. They came in with the redesign commit.

KpiCard: the note pill was removed from the tile but `note` was still
destructured, and `noUnusedLocals` rejects that. The prop stays declared —
87 call sites across 21 files pass it — and is now documented as accepted
and ignored, the same way `fill` already was. Those 87 strings are written
and never shown; the comment says so rather than leaving it a puzzle.

InventoryPage: dropped an unused SectionHeader import, and `colour` is not
a BadgeProps field. The intent was a brand-coloured "In transit", so that
is now `variant="purple"` — a real variant in BadgeVariantMap, and the
brand is purple.

StoreAccountPage: `current` is a BRANCH, and `gettenantlocations` sends no
tenantname on it (checked on the wire against tenant 1147). So the second
half of `shopQuery.data?.tenantname || current?.tenantname` could never
fire. Removed rather than added to the type — a field the backend does not
send is exactly the bug the previous commit fixed on the summary endpoints.

Verified: tsc clean, 625 tests pass, vite build clean, and the lock file
installs under `npm@10.9.8 ci` — the builder's npm, which the image pins.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JYEsb8PNZ19G9R8gUjTU7n
2026-09-11 16:50:39 +05:30
0a11f7543c redesign 2026-09-11 16:32:50 +05:30
81b7d32672 deploy fix 2026-09-10 18:05:45 +05:30
8b2c4daef8 updats on the dispatch page 2026-09-10 17:57:00 +05:30
79a8f2b234 map is the resting state of the rider and store views
Opening dispatch showed "Pick one to see its stops" over an empty panel.
That wastes the first look: the whole day IS the answer to "where is my
work", and an operator usually only wants to narrow after seeing it.

Both views now open on the map, drawn from every stop in range. Picking a
rider or a shop filters it; it no longer summons it. The customer view keeps
its placeholder — one customer's drops are all at one address, so there is
no shape to open onto.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JYEsb8PNZ19G9R8gUjTU7n
2026-09-10 11:26:09 +05:30
35250717fc map the selected rider and shop, drop the map tab
The separate Map tab is gone. "By rider" and "By store" now draw the map
where the stops table was, so picking a rider from the rail shows their
round on a map and picking a branch shows its day.

A round and a shop's day are both shapes — where the work is, in what order,
how far apart — and a table of addresses shows neither. You can read twenty
rows and still not see that a rider crossed the city twice.

Two views keep the table, on purpose: the waiting queue, whose rows are
ticked to assign them (a checkbox cannot live on a map pin, and nothing
there has been worked yet), and "By customer", where one customer's drops
are all at one address.

The map draws all three places a delivery has, not just the rider:

  shop   a square, one per branch — pickuplat/pickuplon, 500/500 rows
  drop   a circle per stop, by status — droplat/droplon, 500/500 rows
  rider  a hollow ring — riderslat/riderslon, 461/500 and 324/500

Shop and drop are on every row, so the map is never empty on a day with
work in it. The rider fix is real: on delivered rows it sits a median 134 m
from the drop, a reading taken at the customer's door.

The endpoints spell the columns differently — `pickuplon` on getdeliveries
against `pickuplong` on getorders, one letter, and reading the wrong one
puts every shop off the coast of Ghana. `droplat` is filled on deliveries
and empty on orders. `coordOf` takes every spelling so a waiting order maps
the same as a delivered one.

Also fixes the rail itself: it named each group from its first stop's
`ridername`, and that column holds a delivery status on more rows than a
name for two riders in five. The board was listing a phantom rider called
"delivered" carrying 100 of the day's stops, next to the real riders.
Grouping was never wrong — that is on userid — only the label. `isRealName`
now excludes the status vocabulary and both the rail and the map take the
most common name that survives.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JYEsb8PNZ19G9R8gUjTU7n
2026-09-09 17:47:40 +05:30
34bf7989f7 dispatch map, plan vs actual, and a fleet page
Three of the features the old console had and ours did not, built on what
the data can actually support rather than on what the column names imply.

Two findings changed the shape of the work:

`riderlogs` is not a GPS trail. Every ping a rider sends carries the SAME
coordinate — one rider's 2,404 pings on 14 August all read 11.052998,
76.929958, and the same holds on every day and region checked. Distance,
speed and "time moving" cannot come from it. The Fleet page therefore
reports presence only: who was online and for how long, inferred from the
gaps between check-ins, because `login`, `logout` and `workhours` are empty
on all 320,132 August rows. It says out loud that it cannot tell a rider
parked all day from one who crossed the city.

The delivery ladder is not the order its columns are in. `starttime` is
later than `arrivaltime` on 316 of 316 rows, which looks corrupt and is not:
`starttime` is per-DROP, stamped when the rider sets off for that address
having finished the last one. Read as assign -> arrive -> pickup -> start ->
deliver, every duration is positive. On tenant 916 that shows the bottleneck
is not the riding: a median 69.5 minutes passes between handing an order to
a rider and that rider reaching the shop, against 0.6 minutes at the counter.

- Map tab on dispatch, fed by `deliveries.riderslat/lon` — the only rider
  positions that move (353 distinct across 461 rows). Tenant-scoped, so a
  shop sees its own rounds. The line joins stops in worked order and says
  it is not a route.
- Plan vs actual tab: promised against delivered, and a step breakdown of
  where the hours go. `actualkms` is excluded — it equals the planned `kms`
  to the decimal on every delivered row, so it is a copy, not a measurement.
- Fleet page in the platform console: a presence gantt and a map of where
  each rider is registered.
- `ridername` holds a delivery status on more rows than it holds a name for
  two riders in five, so names are resolved by excluding the status
  vocabulary first.
- leaflet, wrapped directly rather than via react-leaflet, lazy-loaded so
  only the pages with a map pay for it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JYEsb8PNZ19G9R8gUjTU7n
2026-09-09 17:02:21 +05:30
b760c1a078 rider partner page 2026-09-09 15:43:23 +05:30
32c612a10d qr code 2026-09-09 11:19:05 +05:30
a94c23c20e profile name change 2026-09-08 19:20:42 +05:30
035ceb44a7 profile page 2026-09-08 19:01:40 +05:30
33c4542ddf guide 2026-09-08 17:03:17 +05:30
59828811f9 timing 2026-09-08 15:40:48 +05:30
024fc4adfd bulk release 2026-09-08 12:59:17 +05:30
12269deeda category id 2026-09-08 12:17:56 +05:30
d54fadef20 category changes 2026-09-08 12:03:23 +05:30