- 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.
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.
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.