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.
This commit is contained in:
Nathnael
2026-08-13 08:53:03 +00:00
parent 58b47318e9
commit 6a102bf938
10 changed files with 293 additions and 187 deletions

View File

@@ -41,7 +41,7 @@ import InvoicesPage from "./pages/invoices/InvoicesPage";
import UsdPaymentsPage from "./pages/invoices/UsdPaymentsPage";
import MyProfilePage from "./pages/dashboard/MyProfilePage";
import OverviewPage from "./pages/dashboard/OverviewPage";
import ReportsHubPage from "./pages/reports/ReportsHubPage";
import ReportsIndexRedirect from "./pages/reports/ReportsIndexRedirect";
import ReportPage from "./pages/reports/ReportPage";
import AuditLogsPage from "./pages/AuditLogsPage";
import AiBookingMockTestPage from "./pages/ai/AiBookingMockTestPage";
@@ -214,7 +214,7 @@ const App = () => {
<Route path="/dashboard" element={<Navigate to={landingPath} replace />} />
<Route path="/dashboard" element={<DashboardShell />}>
<Route path="overview" element={<RequirePermission permission={FREIGHT_PERMS.overview.view}><OverviewPage /></RequirePermission>} />
<Route path="reports" element={<RequirePermission permission={FREIGHT_PERMS.reports.view}><ReportsHubPage /></RequirePermission>} />
<Route path="reports" element={<RequirePermission permission={FREIGHT_PERMS.reports.view}><ReportsIndexRedirect /></RequirePermission>} />
<Route path="reports/:reportKey" element={<RequirePermission permission={FREIGHT_PERMS.reports.view}><ReportPage /></RequirePermission>} />
<Route path="audit-logs" element={<RequirePermission permission={FREIGHT_PERMS.auditLog.view}><AuditLogsPage /></RequirePermission>} />
{/* Dev/testing page for the mock AI booking assistant. */}