Commit Graph

34 Commits

Author SHA1 Message Date
Nathnael
4a4d3077d7 feat: Stripe-style filter bar for freight backoffice (pilot: contracts)
Replace the ad-hoc filter controls with a URL-linkable pill filter bar:
each filter is a pill that opens a type-aware popover (text/enum/date/
number/boolean, each with the right operator set), overflow filters live
behind a searchable "More filters" menu, sorting is a separate control,
and filter state round-trips through the URL query string (shareable,
back/forward-safe, backward compatible with existing ?statuses=A,B links).

Frontend (apps/edr-freight-web/backoffice/src/components/filters/):
- FilterDef schema + a pure url.ts codec (parse/serialize/toApiParams),
  with a 24-case round-trip + malformed-input test suite
- useFilters hook driving react-query params straight from useSearchParams,
  debounced search, saved views in localStorage (@mantine/hooks
  useLocalStorage), page-reset-on-filter-change baked into one
  setSearchParams call instead of a separate effect
- FilterBar/FilterPill/OperatorSelect/MoreFiltersMenu/SortControl +
  per-type popover bodies (Mantine)
- ContractRequestsPage migrated end to end as the pilot

Backend (apps/edr-freight-api):
- pagination.util: applySort() — whitelisted sortBy resolved against a
  per-module column map (never interpolated), with a mandatory `id ASC`
  tiebreaker so paginating a non-unique sort can't drop/duplicate rows
- facets.util: computeFacets() — one GROUP BY per enum column, each
  omitting its own predicate, so picking a value doesn't hide its siblings
- contracts/bookings: list-summary now returns real filter-scoped facet
  counts (contracts' getStatusCounts was unfiltered/global; superseded)
- deleted drivers/vehicles findAllWithFilters — dead code that
  interpolated an unwhitelisted sortBy straight into orderBy()
- migration: missing bookings(status)/wagons(status) indexes +
  (created_at DESC, id ASC) partials on the hot list tables

UI polish pass: inactive pill uses the opaque "default" variant instead
of a faint tinted outline, active pill uses "light" not "filled", larger
X hit target, applied filters sort first, sort control separated behind
a divider on the right and wraps independently from the filter row,
popover option rows are fully clickable (count moved inside the native
label) with bigger hit area and font, fixed a real date-filter bug where
the calendar's own portal falsely registered as an "outside click" and
closed the popover, and fixed a timezone bug where bare YYYY-MM-DD
strings were parsed as UTC instead of local time (shifts a day for EAT).

Not in this commit: rollout to the other ~59 list pages, the Ethiopian-
calendar DateBody branch, and the Family-B (client-side) bridge mode —
tracked in the filter-bar plan.
2026-08-14 13:18:46 +00:00
Nathnael
da08a9b085 fix(auth): list every route key on the class-level guard
Nest runs class and method guards together, so a class gate naming only
the view key silently required view AND action. Staff granted just an
action were denied before their key was checked. Each class gate now
names every key its routes use, and FleetView accepts an array so the
fleet controllers keep their coarse fallback.

Drops the one-off grant mapping SQL with it: already applied to dev, and
this fix removes the companion-view rule that was its recurring part.
2026-08-07 08:43:20 +00:00
Hagernesh
cf8a2e928d fix(warehouses): detention groups by canonical truck type
Join truck_types via vehicles.truck_type_id (normalized legacy
vehicle_type only as fallback) so type renames can't unmatch detention
rules and FK-less vehicles keep billing.
2026-07-24 11:55:05 +00:00
Hagernesh
89d82f45c6 fix padding on portal 2026-07-21 14:01:10 +00:00
Hagernesh
b616f520ae feat(fleet): validate vehicle plate numbers against a letters-and-digits format
Plate, power-plate and trailer accepted any free text — a vehicle could be
saved with a plate of "assadasd". They must be letters, a hyphen, then digits,
like ET-9875 or AA-8642.

The server now enforces it on CreateVehicleDto (and UpdateVehicleDto via
PartialType): each plate is trimmed and upper-cased, then matched against
^[A-Z]{2,3}-\d{2,6}$, so "et-9875" is accepted and stored as ET-9875 while an
empty optional trailer/power plate still passes.

The fleet form gains the same check inline: FleetFormFieldDef takes an optional
pattern, the dialog tests it on submit against the upper-cased value, and the
vehicle config points plate and trailer at a regex that mirrors the server's.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 11:03:40 +00:00
natib21
b300fd1de5 user permition 2026-07-07 10:00:48 +00:00
natib21
fb4ffa5d67 fix 2026-07-06 12:23:25 +00:00
natib21
998a6801ab fleet 2026-07-06 12:05:52 +00:00
natib21
c643d30624 fix 2026-07-03 15:47:12 +00:00
natib21
0e6ebda6f6 fix 2026-07-03 15:21:23 +00:00
natib21
b7da024968 fix 2026-07-02 14:37:38 +00:00
natib21
2424e96e74 fix 2026-07-02 14:34:22 +00:00
natib21
e5fed081fc fix 2026-07-02 14:27:09 +00:00
natib21
7d85f5dc2e fix 2026-07-02 14:18:53 +00:00
natib21
c2c29f0735 fix 2026-07-02 14:14:13 +00:00
natib21
7f6c9c6313 fix 2026-07-02 13:55:08 +00:00
natib21
58b3805d0b fix 2026-07-02 12:43:03 +00:00
natib21
a0f4de05f8 log full error 2026-07-02 12:37:02 +00:00
natib21
ff7e20d2ee fix 2026-07-02 11:22:35 +00:00
natib21
f5eaa87564 fix ui 2026-06-27 14:15:14 +00:00
hagiye
f4a90755c2 api 2026-06-25 11:00:40 +03:00
hagiye
46bfa9cb87 Release Order plus Storage Allocation Rule and fee 2026-06-24 16:21:45 +03:00
hagiye
8ee31789c6 merge conflict fix 2026-06-24 12:31:59 +03:00
natib21
79860c807c fix 2026-06-24 09:30:11 +00:00
hagiye
0255adffe6 changes 2026-06-24 09:56:12 +03:00
hagiye
79efa1ec60 Warehouses confilct fix 2026-06-21 19:06:51 +03:00
natib21
963392edb3 fix data table 2026-06-20 09:38:12 +00:00
yaschalew
55663a5c43 fix 2026-06-20 09:52:32 +03:00
natib21
58bfb5045a vehicle 2026-06-19 12:25:00 +00:00
natib21
0397a36370 vehicle 2026-06-19 11:54:12 +00:00
yaschalew
3352333bef fix 2026-06-18 12:49:47 +03:00
natib21
fc702f0fbe driver 2026-06-18 09:46:35 +00:00
yaschalew
5c070d239e fix save 2026-06-18 12:32:44 +03:00
natib21
58fcf9ce3f fix data integrity issue 2026-06-18 07:13:08 +00:00