Appearance
Pending Approvals
Paginated list of worker approval requests (holidays, illness/absences, timesheets, expenses) with filtering by type, status view, and search. Supports approve/decline actions via modal.
Route
/organisations/:organisationId/pending-approvals
Accepts optional query parameters:
view-- Pending, Approved, Rejected (default: Pending). Paid and Overdue views are conditionally available.filter-- Request type name (e.g. "Holiday", "Expense")query-- Comma-separated search terms (worker names)
Sub-routes
/organisations/:organisationId/pending-approvals/:approvalId -- Detail view for a specific approval.
Roles
CompanyAdmin, CompanyOwner, TeamAdmin, TenantAdmin
Layout
Statistics Bar
Rendered by the StatisticsList component. Displays approval counts by request type, fetched via getApprovalOrganisationStats. Stats are scoped to the selected view and billing entity. Each type is clickable to filter the list. Types shown depend on tenant license (filtered via filterUnusedApprovalStats):
- Holiday -- Hidden when
tenantLicense.absencesEnabledis false. - Illness -- Hidden when
tenantLicense.absencesEnabledis false. - Timesheet -- Always shown (if timesheets exist).
- Expense -- Hidden when
tenantLicense.expensesEnabledis false.
Clicking a type toggles it as the active filter via selectRequestType. Clicking the same type again clears the filter back to "All".
Search and Filter Bar
Rendered by the SearchFilter component:
- View selector dropdown: Pending, Approved, Rejected. "Paid" is added when the Expense or Timesheet type is selected (via
updateViewSelections). - Search input with local autocomplete (matches against
requesterNamein loaded approvals viagetSearchFieldSuggestions). - Active type filter displayed as a removable chip. Removing a type filter resets the view to Pending if it was on Paid.
- View selection is cached in session storage.
Grid/List Toggle
Controlled by the pendingApprovalsListViewSelected store:
List view -- Table with columns:
- Checkbox (
th-box, fixed 3.75rem width) - Name (
th-name) - Type (
th-type, clickable column header toggleshrOnlyfilter viatoggleHrOnlyFilter) - Request (
th-request) - Status (
th-status) - Approvals (
th-approvals, approval chain progress) - Date Submitted (
th-date-submitted) - Calendar (
th-calendar, date range) - Note (
th-note)
Each row is rendered by PendingApprovalTableRow.
Grid view -- ApprovalCard components with:
- Type-specific icons (
ExpenseIcons,AbsenceIcons,AnnualLeaveIcons,TimesheetIcons) in theiconsslot - Approval status labels
- Approver chain display
- Footer with Approve/Decline buttons (
ApprovalButtonsin thefooter-actionsslot)
Card props are derived via toApprovalCardProps(approval).
Approval Actions
Clicking an approval item in either view navigates to /organisations/:organisationId/pending-approvals/:approvalId (preserving the current query string).
Approve and Decline buttons open a PendingApproval modal:
- Approve: confirms the approval.
- Decline: sets
isDeclineSelectedand shows decline-specific content in the modal. - On completion (
requestCompleteevent), the approval is removed from the pending list and the list is refreshed by re-applying the current filter.
Pagination
- Items per page selector via dropdown: 10, 25, 50, 100, 200.
- Page size preference persisted in
pendingApprovalsListPageSizestore. - Changing view, type filter, or search terms resets to page 1 (via
resetPagination). - Sticky pagination section at bottom of viewport (
.pagination-sectionwithposition: sticky; bottom: 0). Paginationcomponent receivestotal,current, andpaginationLimitprops.
Data Loading
- Approvals fetched via
getPendingApprovalByOrgIdAndBillingEntitywith search parameters including billing entity, page, page size, view, type, filters, and hrOnly flag. - Statistics fetched via
getApprovalOrganisationStatsscoped to the selected view and billing entity. - Holiday and absence stores updated internally via
updateHolidayStoreInternalandupdateAbsencesStoreInternalafter each data load. - On mount, cached view, approval type, and queries are restored from query parameters.
Behavior notes
- On fetch failure, an error notification is shown via
showErrorNotificationand an empty list is displayed. - The
hrOnlyfilter is toggled by clicking the "Type" column header in list view. - View selection is cached in session storage via
sessionStorage.setItem('selectedView', ...). - List view table headers are responsively hidden below 1200px: Date Submitted, Calendar, Status, Type, and Note columns are removed via CSS
display: none. - A skeleton loading animation (8 rows with
skeleton-loadingkeyframe) is shown while data loads. - The "items per page" text is hidden on mobile screens narrower than 550px (
.hide-on-mobile).