Commit Graph

681 Commits

Author SHA1 Message Date
Nathnael
54cf0c2944 fix(filters): make the whole filter option row clickable
The padding around an enum filter's checkbox/radio carried the hover cue but
swallowed the click: the only element that toggles a Mantine Checkbox is its
native <label>, which wraps its own text and nothing else. The row's padding
and the gutter beside the input square lie outside it, so styling those on
`root` produced an area that looked interactive and was not.

Stretch a `::before` over the relatively-positioned root. The pseudo-element
belongs to the label's own box, so a click anywhere in the row lands on the
label and toggles the input. `cursor: pointer` moves to the root for the same
reason -- the affordance should cover exactly what is clickable.
2026-08-20 09:05:31 +00:00
Nathnael
87ec7cec07 fix(export-ui): let field groups be expanded and collapsed by hand
The accordion's open state was derived from the selection on every render,
which made it fully controlled with nothing driving it. Clicking a group that
had no fields selected opened it for one render and the recomputed value
immediately shut it again, so such a group could only be opened by selecting
something inside it — and conversely a group with a selection could not be
collapsed at all.

Open state is now real state with an onChange, seeded from the fields marked
default rather than the live selection, so clearing every field doesn't close
the groups underneath the user. Search still force-opens every group holding a
match, but only as a display override — the manual state survives and returns
when the search clears.
2026-08-20 08:25:47 +00:00
Nathnael
6e95c5b8b8 fix(backoffice): map overview layouts to the org's real position keys
The overview layout table matched invented keys (`edr_operations_officer`,
`edr_marketing`, …) that only ever existed as IAM roles. The positions
actually configured under the unit use their own keys — `edr_freight_app/opn`,
`ethiopian_gl`, `edr_freight_app/finance` — so most staff fell through to the
executive fallback regardless of desk.

Map every position key in the current org tree, roots and sub-positions
alike, and keep the legacy role-form keys so accounts that model the desks
as roles still resolve. Finance was previously unmapped entirely.

Also drop a stray console.log from resolveOverviewLayout.

Safety (`edr_freight_app/sf_146`) stays unmapped — no such layout exists yet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 08:20:00 +00:00
Nathnael
42b9f30057 feat(export-ui): field-picker export dialog, mounted on bookings
A Stripe-style export dialog over the /exports catalog: searchable field
picker grouped by related entity, format choice, row scope, saved presets,
and a live row count.

The picker is what makes 77 fields usable. Groups auto-expand only when they
already hold a selection, so the dialog opens showing the default columns and
their groups rather than a wall of checkboxes; searching force-expands so a
match can't hide inside a collapsed group. Group headers carry a tri-state
checkbox and an n/total badge.

The row count comes from /exports/:key/count with the page's own filters, so
the button reads 'Export 223 rows' before anything is downloaded, and turns
into a cap warning with a one-click 'export the first N' escape when the
result is too large for the chosen format.

ExportButton takes plain params rather than a UseFilters instance —
four of the pages that need this haven't migrated to FilterBar yet, and
coupling to the hook would have blocked them. Pagination keys are stripped in
one place instead of at every call site. It renders nothing when the catalog
omits the dataset, so the catalog's permission filtering IS the UI gate.

Presets reuse useSavedViews unchanged by encoding the preset as a query
string; a preset naming a field the catalog no longer offers is dropped on
load rather than 400ing the download. Download errors go through
extractDownloadErrorMessage, without which the server's row-cap message
degrades to 'Request failed with status code 400'.
2026-08-20 06:44:29 +00:00
Nathnael
fb21ad1541 feat(WIP): filtering, exporting and more reports 2026-08-19 13:51:18 +00:00
Nathnael
e964a9b8f4 chore: more reporting 2026-08-19 10:14:46 +00:00
Nathnael
54f52f077c fix(page-header): cap title/subtitle width
Title and subtitle grew unbounded, relying only on flex-squeeze from action
buttons to ever truncate. Caps the container at 640px and gives the
subtitle the same truncate treatment the title already had, so a long
page title or description (report descriptions in particular) always
ellipses instead of stretching the header.
2026-08-19 10:12:16 +00:00
Nathnael
6687def4af feat(reports): use the shared FilterBar instead of ReportFilters
Swaps ReportView's bespoke ReportFilters for the same FilterBar/useFilters
combo BookingRequestsPage uses — pills, saved-view-ready state, URL sync.
toFilterDefs() maps the report catalog's own filter vocabulary
(daterange/date/select/multiselect/text) onto FilterDef, matched against
every report definition's backend param handling. The search box only
shows for reports that actually implement `search` server-side, so it's
not a dead control on the rest. ReportFilters.tsx is now dead, removed.
2026-08-19 10:12:03 +00:00
Nathnael
7c56607582 fix(filters): honor a date filter's own operator, not always "between"
DateBody always initialized its op state to DEFAULT_OP.date ("between"),
ignoring a def's `operators` restriction. A single-operator exact-date
filter (e.g. `operators: ["before"]`) opened on the range UI with no way
off it, since OperatorSelect hides itself when there's only one choice.
Default to the def's first allowed operator instead.
2026-08-19 10:11:48 +00:00
Nathnael
7aa4405423 Merge branch 'dev' into freight/nati-2
Conflict in ClearanceDocumentsPage: this branch migrated the page to the
pill FilterBar, dev added filters to the Select stack it replaced. Kept
the FilterBar and carried dev's additions across as a "Booked by"
(customerKind) FilterDef plus the shipping-line search placeholder; dev's
startOfDayIso/endOfDayIso went away because dateRangeParams already does
that. The Ship icon import is needed by dev's shipping-line customer cell,
which merged cleanly on its own.
2026-08-17 12:43:35 +00:00
Nathnael
7143ba1040 feat(customers): notify marketing on returned changes, name actors in history
Three gaps on the backoffice customer detail page:

- Rejecting a change request or sending it back for correction notified
  nobody. Adds CompanyNotifierService.changeRequestReturned, which pings
  the customer desk with the reviewer, the outcome and the note. Marketing
  joins that desk via customers:view + customers:get_notification in the
  role preset — grants still come from the IAM UI, the preset only sets
  the default for new environments.
- submitted_by / reviewed_by / actor_id were stored but never resolved, so
  the History tab could say what changed but never who asked or who sent
  it back. Resolves them through a shared iam-user-name util (deduped from
  the private copy in contract-document-history.service) and renders
  "Requested by" / "Sent back to marketing by" lines. The
  changes_requested badge is relabelled to match the workflow.
- "View" opened an in-page modal one document at a time. Adds
  openFileInNewTab, which opens the tab inside the click gesture and fills
  it once the authenticated fetch resolves, and an "Open all" button that
  loops over the documents table so every file lands in its own tab.
2026-08-17 12:38:06 +00:00
Marshal
9f53114778 feat: enhance booking management with shipping line support and cargo handling improvements 2026-08-15 18:48:33 +00:00
Marshal
ca9f631f6f Merge branch 'dev' of github.com:Tria-plc/edr-platform into freight_feature/usermanagement 2026-08-15 10:12:59 +00:00
Marshal
dc38e843a6 feat: full wagon cancel, leg board, wagon dates
feat(freight): editable train leg times, SL invoice payer
2026-08-15 10:12:37 +00:00
Marshal
c9c2d4dcb3 booking cancellation 2026-08-15 08:53:24 +00:00
Hagernesh
47c2e82839 feat(freight-backoffice): EIMS cancel/receipt/memo actions in filing card
Adds cancel, sales/withholding receipt filing + listing + PDF download, and
credit/debit memo issuance to EimsFilingCard, each gated on its own
permission.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 08:38:35 +00:00
Nathnael
4b4ab21ea1 fix(filters): auto-apply radios, route popover bug, date operators, polish
- Radio-based filters (single-select enum, boolean) apply the instant
  an option is picked and close — no Apply click needed. Checkbox
  (multi-select) keeps the explicit Apply, since picking several is a
  multi-step gesture.
- Route filter's Select dropdowns portal separately by default, so a
  click landed as "outside" the outer pill popover and closed it
  before a pick registered — same class of bug DateBody had.
  `comboboxProps={{ withinPortal: false }}` fixes it.
- Route filter now pinned by default on both pages instead of behind
  More filters.
- Date filter: widened to before/between/after (repository already
  applies each bound independently) via a new `dateRangeParams`
  helper — the old positional `{v[0]:from, v[1]:to}` mapping silently
  put a "before" pick in the from param. Added a calendar icon + sm
  sizing, and a wider popover so the range presets sidebar has room.
- Pill's clear (X) button enlarged; search box border/text opacity
  strengthened to match the pill trigger restyle.
2026-08-15 07:31:19 +00:00
Nathnael
839dfdbae3 feat(filters): route filter, select-styled trigger, tune default pin set
- New "route" FilterType: RouteBody popover (searchable origin +
  destination selects, apply once both are picked), wired into
  ContractRequestsPage and BookingRequestsPage. Bookings already had
  server-side originYardId/destinationYardId; contracts gets both new
  (contract_routes is one-to-many, so origin/destination are separate
  EXISTS subqueries, not a join).
- Inactive FilterPill trigger restyled to read like a closed Mantine
  Select (opaque solid border, trailing chevron) instead of a dashed
  "+" pill — trigger only, popover body/position unchanged.
- Search box text set to regular weight.
- A couple more filters (Direction, Freight) pinned by default per
  page on top of the existing always-pinned ones; the rest stay behind
  More filters.
2026-08-15 07:23:43 +00:00
Nathnael
e5e75b4166 feat(filter-bar): migrate 3 more fleet pages, extract footer adapter
- ruleEngineFooterProps.ts: toRuleEngineFooterProps() — the
  useFilters-to-RuleEngineListFooter pagination adapter had already been
  hand-written twice (TrucksOnSitePage, CompliancePage) with the same
  pageSize-drop risk useFilters itself just had fixed; extracted before a
  third copy could drift.
- CompliancePage, FuelPurchasePage, IncidentsPage: ListControls ->
  FilterBar + applyClientFilters, same mechanical pattern as the
  warehouse pages (search + one date range, endpoints take no params at
  all per the inventory sweep — confirmed correct bucket, not assumed).
2026-08-14 14:13:11 +00:00
Nathnael
d94c444a51 feat(filter-bar): fix pageSize bug, add client bridge, migrate 4 more pages
fix(useFilters): pageSize was a hardcoded constant, never read from the
URL, with no setter — the DataTable/RuleEngineListFooter page-size
dropdown silently did nothing on every page using the filter bar,
including the already-shipped ContractRequestsPage pilot. Added a `size`
URL param (mirrors `page`), `setPageSize`, and wired
`tableProps().onPaginationChange` to route page-size vs page-index
changes to the right setter instead of only ever calling setPage().

feat(clientFilter): applyClientFilters — the Family-B bridge the plan
called for. Generalizes ListControls'/useListControls' one hardcoded
search box + one date range to every FilterDef, matched against
`row[def.key]`. Reuses matchesDayRange/toDayString from
hooks/useListControls.ts (imported, not duplicated) so the inclusive-
range/timezone-safe semantics stay defined in exactly one place. Lets a
page ship the full pill-bar UI immediately and flip to server-side
filtering later by deleting one function call — no endpoint changes
required up front.

Migrated to the filter bar (mechanical, pattern established by
ContractRequestsPage):
- WarehouseInvoicesPage, LoadedInventoryPage, TrucksOnSitePage — Family B
  (ListControls/useListControls → FilterBar + applyClientFilters)
- CustomersPage — Family A (useState bag → useFilters), no filter pills
  needed here (search + sort only), the SegmentedControl "view" stays
  page-level tab state (like ContractStatusTabs), not a filter pill —
  it now resets the page via controls.setPage(1) on change, the same
  hazard useFilters already guards its own filters against
2026-08-14 14:03:33 +00:00
Nathnael
a15d4d922e Merge branch 'dev' into freight/nati-2 2026-08-14 13:52:23 +00:00
Nathnael
524f9aab56 fix(filter-bar): responsive layout broken on narrow viewports
The two-zone layout (left: filters, right: sort+save) hardcoded
flexWrap: "nowrap" on the outer container so the right zone would never
get pushed below the left on desktop. On a phone that's the same
two-column squeeze with no room for either side: the search box and
right-hand controls got clipped/overlapped instead of stacking.

- outer container: flex-col below the `sm` breakpoint (stacks to two full-
  width rows), flex-row + nowrap at `sm` and up (the original two-zone,
  right-pinned behavior)
- right zone swapped from <Group wrap="nowrap"> to a plain div with
  Tailwind classes — Group's `wrap` prop sets an inline flex-wrap style,
  which always wins over a `sm:flex-nowrap` class regardless of
  breakpoint, so the old responsive attempt could never have worked
- search input's hardcoded minWidth: 220 (wider than a lot of phones)
  dropped to a shrinkable 160
- saved-view card grid: base 2 columns forced text-clipping card overflow
  on a phone; base is now 1, growing to 2+ only once there's room
2026-08-14 13:51:48 +00:00
Nathnael
bec9575311 refactor(filter-bar): saved views as auto-named cards, not a name-prompt menu
Replace the modal "type a name to save" flow with a one-click Save that
auto-generates the label from the active filters (describeQuery, reusing
the same formatter FilterPill uses for pill text — one source of truth,
nothing to type, nothing to fall out of sync). Saved views render as a
grid of cards at the top of the filter bar instead of being buried in a
dropdown.

- useSavedViews: localStorage state, extracted so FilterBar owns one
  instance instead of two components each subscribing separately
- SaveViewButton: filled (not outline) since it's the one action-y
  control among a row of filter pills; flashes to a disabled "Saved" +
  checkmark state for 1.5s on click, in addition to the corner toast —
  the toast alone wasn't registering as feedback
- SavedViewCards: click to apply, per-card delete, active one highlighted
- moved from the wrapping filter-pill row into the pinned right-hand zone
  (with sort) behind its own divider, so it can't shove pills around
- Save icon: BookmarkPlus -> Save (floppy disk reads as "save" faster)
- More filters button: outline/gray -> default variant — same low-
  contrast-outline problem the inactive filter pill had
- Clear button font bumped xs -> sm to match the rest of the bar
2026-08-14 13:48:54 +00:00
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
Hagernesh
b4f2ec1c75 feat(train-scheduling): load returned empties onto an export train
Empties had no way onto a departure: the return record could name a train
but nothing seated it on a wagon. Export schedules now expose a loading
action that packs selected returns onto free wagons at one 40ft or two 20ft
each, enforced both in the picker and in the API (existing empties on the
schedule count against their wagon).

Adds container_size, train_schedule_id and wagon_sequence_no to
freight.empty_container_returns.
2026-08-14 09:57:50 +00:00
Nathnael Wondisha
553524ee56 Merge pull request #1280 from Tria-plc/freight/nati-2
Freight/nati 2
2026-08-13 22:16:04 +03:00
marshal
e17df57a37 Merge pull request #1279 from Tria-plc/freight_feature/usermanagement
Freight feature/usermanagement
2026-08-13 21:58:33 +03:00
Marshal
b9ba830a09 shipping line 2026-08-13 18:56:52 +00:00
Nathnael
147887b7c5 feat: dashbaord overview 2026-08-13 18:13:42 +00:00
Marshal
0e00a98ef3 feat: implement shipping line booking completion functionality
- Added ShippingLineBookingCompletionController and associated service to handle the completion of shipping line bookings.
- Introduced a new module for booking completion to maintain module separation and avoid cyclic dependencies.
- Updated the train scheduling global rules to set default desk hours to 24 hours.
- Modified existing services and entities to accommodate the new booking completion logic.
- Enhanced the front-end components to support the new booking completion flow, including updates to the booking detail and bookings pages.
- Implemented validation and error handling for booking completion, ensuring that only approved bookings can be completed.
- Added migration to set default desk hours in the database.
2026-08-13 15:10:27 +00:00
Marshal
5837ac7b6e Merge branch 'dev' 2026-08-13 14:14:31 +00:00
Nathnael
89cdc0ad06 style: ui fixes 2026-08-13 13:46:46 +00:00
marshalyordanos
9fff469ffa feat: implement shipping line bookings management
- Add ShippingLineBookingsPage for listing and managing shipping line bookings.
- Create ShippingLineDocumentsModal for document uploads related to bookings.
- Introduce ShippingLineInitiateModal for initiating new shipping line bookings.
- Implement booking document state management with booking-doc-state utility.
- Add shipping line bookings service for API interactions.
- Update index to export new components and services.
- Enhance types for freight to include shipping line credits.
2026-08-13 15:54:40 +03:00
Nathnael
0df4be1820 style: overview revamp 2026-08-13 12:44:06 +00:00
Nathnael
3190b9bd38 Merge branch 'dev' into freight/nati-2 2026-08-13 11:34:57 +00:00
Nathnael
86d69a9577 chore: group invoices, payments and usd payments 2026-08-13 11:22:45 +00:00
Hagernesh
c4bf3c9479 feat(freight): add company logo setting applied to every generated document
New logo-settings module (mirrors stamp-settings): single uploaded logo,
stored via FilesService/MinIO, injected as a data URL into invoice/receipt,
contract, warehouse, train-scheduling, and payment-receipt PDFs. Adds a
matching backoffice settings page and settings:logo:view/manage permissions.

>
2026-08-13 10:54:23 +00:00
Nathnael
4ae63d4e5c fix: report ordering 2026-08-13 09:29:09 +00:00
Hagernesh
58cb71a9cf feat(train-scheduling): add direct truck-to-train load action beside Load
Export bookings whose cargo goes straight from customer truck to wagon
never get a warehouse GRN, so the load gate (assertExportReceivedWithGrn)
rejects them forever unless staff first flip exportHandoverMode on the
booking detail page, then come back and retry Load.

Add a Truck to Train button next to Load in the schedule workspace's
on-train list, shown for EXPORT bookings at the boarding yard. One click
sets exportHandoverMode=DIRECT_TO_TRAIN then loads the booking.
2026-08-13 08:55:17 +00:00
Nathnael
6a102bf938 feat(reports): header actions, single export dialog, date-range presets
- ReportPage drops its own PageHeader (and the back arrow); ReportView
  now optionally renders the header itself (pageHeader prop) with
  export/refresh as its actions. Embedded ReportSection usage is
  unaffected (keeps the inline toolbar next to filters).
- Replace the two xlsx/pdf icon buttons with one Export button opening
  a dialog: format as large icon radio cards, fields as checkboxes
  (select-all toggle), record count (default all, capped per format).
  Export applies the report's current filters and sort.
- Backend: export route accepts fields (whitelisted against the
  report's own columns) and limit; ReportExportService takes an
  optional column subset instead of always dumping every column.
- Fixed a real bug found while wiring this up: runAll() ignored the
  caller's sortBy/sortOrder and always used the report's default sort,
  so exports silently didn't match whatever order was on screen.
- Report daterange filters now use DatePickerInput + the shared
  getDateRangePresets() (Today/Last 7 days/This month/...) instead of
  two bare DateInputs, matching every other date-range filter in the
  app.
- Removed the reports hub grid page. /dashboard/reports now redirects
  to the first report the caller has access to, or /dashboard if they
  have none.
2026-08-13 08:53:03 +00:00
Nathnael
58b47318e9 feat(freight-backoffice): consolidate Mantine from/to date filters into range pickers
Replaces every remaining split from/to Mantine DateInput/DatePickerInput pair
with a single DatePickerInput type="range", sharing one preset list (Today,
Last 7/30 days, this/last month, YTD) via getDateRangePresets(). Covers
ListControls (18 consumers), FleetResourcePage, ContractRequestsPage,
BookingRequestsPage (created + scheduled ranges), WagonCancellationsPage,
BatchBoardPage, ClearanceDocumentsPage, ShipmentRequestsPage.

Native Mantine range picker, not the shadcn DateRangePicker, to match each
page's existing design system instead of clashing with it.

Reports date-range filter (ReportFilters.tsx) intentionally left untouched.
2026-08-13 08:45:29 +00:00
Nathnael
efc5a24380 feat(reports): add optional chart view to the report engine
ReportDefinition gets an optional chart {type: line|bar, x, y[]} field —
plots the same rows the table gets, no separate query. Frontend adds a
table/chart toggle (defaults to table) using the existing recharts
dependency, no new package.

Chart view fetches up to 100 rows (the API's page-size ceiling) instead
of the table's current page, so it doesn't silently plot a fraction of
the filtered set; shows a truncation note past that cap.

Wired onto 5 reports as proof: wagon-fleet-status, locomotive-fleet-
status, booking-status-breakdown, revenue-summary (bar), and
global-logistics-wagons (line). Everything else stays table-only —
charting is opt-in per report, not a default.
2026-08-13 08:34:08 +00:00
Hagernesh
833e62990e feat(train-scheduling): add wagon type, tare, equated length, station, seal no and note columns to import marshalling doc
Import Load List / Marshalling Document only rendered Seq, Wagon,
Booking, Company, Load, Container numbers, Weight T — missing fields
present on the physical marshaling sheet (wagon type, tare, equated
length, departure/arrival station, seal no) and a blank note column
for yard staff. Export marshalling doc already had most of these;
import doc now matches. Existing columns kept in place, unchanged.
2026-08-13 08:25:20 +00:00
Nathnael
081b9945cb feat(freight-backoffice): render reports from the server-driven catalog
Drop reportConfigs.ts (per-report FE config duplicating the backend) and
the chart-drawing ReportPage. Replace with ReportView: one engine that
renders any report the GET /reports catalog describes — filters, KPI
strip, sortable/paginated DataTable, xlsx/pdf export via blob download.
ReportSection embeds a report inline on any page, scoped by idKey, and
renders nothing if the caller lacks that report's permission.

Sidebar Reports submenu is now built from the live catalog
(sidebar-sections.tsx + App.tsx) instead of a hand-listed key — no FE
edit needed to add or hide a report.
2026-08-13 07:52:29 +00:00
Nathnael
d261d6ea7c style: inter module integration 2026-08-13 06:54:54 +00:00
marshalyordanos
9aae132dd4 feat: add shipping line companies management
- Implement ShippingLineCompaniesService for registering and managing shipping line companies.
- Create ResendActivationAction component for resending activation links to shipping lines.
- Develop ShippingLineCompaniesPage for listing and registering shipping lines with validation.
- Introduce shippingLineCompanies.service for API interactions related to shipping lines.
- Define types for shipping line companies, including registration and pagination.
- Add placeholder pages for shipping line portal, including home, bookings, help, invoices, and settings.
2026-08-13 08:54:20 +03:00
Nathnael
5a856027af feat: add email and password 2026-08-12 12:28:37 +00:00
ghost2023
2a816912fc fix(freight-permissions): split company stamp from per-officer teeter permission 2026-08-12 13:18:29 +03:00
ghost2023
02a264930b fix: consolidate stamp settings into single company stamp page 2026-08-12 13:04:18 +03:00
Nathnael
068ee49a9f style: invoice 2026-08-12 09:33:21 +00:00