feat(timesheets): add manager UI to approve/reject submitted timesheets #207

Merged
vas2000-work merged 1 commit from feat/mapps-194-timesheet-approvals-ui into main 2026-06-16 23:50:42 +02:00
Owner

The approval half of the timesheet workflow was unreachable: the backend implements approve/reject (manager-gated) but mokosh-apps had no surface to call them, so submitted weeks sat in "pending" forever. Add a manager/admin "Timesheet Approvals" queue.

  • New /timesheets/approvals route + TimesheetApprovalsPage, gated on can_manage_users() (manager/admin/super_admin) to match the server's RequireManager guard on approve/reject; lower roles see a notice and the page skips the tenant-wide fetch so they never trigger a 403.
  • Lists every user's week summary via GET /timesheets?week= (no user_id, so the server aggregates tenant-wide), keeping the rows still awaiting approval (pending status with entries), behind a week selector that mirrors the employee timesheet page.
  • Per row: Approve posts to the approve endpoint; Reject opens an in-app modal (not window.prompt, per MAPPS-189) that requires a reason and posts it to the reject endpoint. The queue refreshes after each action, and the employee's status badge reflects the new state on their next load.
  • Manager-gated "Timesheet Approvals" nav item under Service Desk.

Note: the acceptance criterion "the rejection reason is visible to the employee" depends on mokosh-server exposing rejection_reason in a response DTO (TimeEntryResponse / TimesheetSummaryResponse never return it today); the reason is captured and persisted by the reject endpoint, but surfacing it on the employee page is a backend follow-up.

#MAPPS-194

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

The approval half of the timesheet workflow was unreachable: the backend implements approve/reject (manager-gated) but mokosh-apps had no surface to call them, so submitted weeks sat in "pending" forever. Add a manager/admin "Timesheet Approvals" queue. - New `/timesheets/approvals` route + `TimesheetApprovalsPage`, gated on `can_manage_users()` (manager/admin/super_admin) to match the server's RequireManager guard on approve/reject; lower roles see a notice and the page skips the tenant-wide fetch so they never trigger a 403. - Lists every user's week summary via `GET /timesheets?week=` (no user_id, so the server aggregates tenant-wide), keeping the rows still awaiting approval (pending status with entries), behind a week selector that mirrors the employee timesheet page. - Per row: Approve posts to the approve endpoint; Reject opens an in-app modal (not window.prompt, per MAPPS-189) that requires a reason and posts it to the reject endpoint. The queue refreshes after each action, and the employee's status badge reflects the new state on their next load. - Manager-gated "Timesheet Approvals" nav item under Service Desk. Note: the acceptance criterion "the rejection reason is visible to the employee" depends on mokosh-server exposing rejection_reason in a response DTO (TimeEntryResponse / TimesheetSummaryResponse never return it today); the reason is captured and persisted by the reject endpoint, but surfacing it on the employee page is a backend follow-up. #MAPPS-194 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(timesheets): add manager UI to approve/reject submitted timesheets
All checks were successful
Check / clippy + fmt + tests (pull_request) Successful in 57s
Create release / Create release from merged PR (pull_request) Has been skipped
fba3675737
The approval half of the timesheet workflow was unreachable: the backend implements approve/reject (manager-gated) but mokosh-apps had no surface to call them, so submitted weeks sat in "pending" forever. Add a manager/admin "Timesheet Approvals" queue.

- New `/timesheets/approvals` route + `TimesheetApprovalsPage`, gated on `can_manage_users()` (manager/admin/super_admin) to match the server's RequireManager guard on approve/reject; lower roles see a notice and the page skips the tenant-wide fetch so they never trigger a 403.
- Lists every user's week summary via `GET /timesheets?week=` (no user_id, so the server aggregates tenant-wide), keeping the rows still awaiting approval (pending status with entries), behind a week selector that mirrors the employee timesheet page.
- Per row: Approve posts to the approve endpoint; Reject opens an in-app modal (not window.prompt, per MAPPS-189) that requires a reason and posts it to the reject endpoint. The queue refreshes after each action, and the employee's status badge reflects the new state on their next load.
- Manager-gated "Timesheet Approvals" nav item under Service Desk.

Note: the acceptance criterion "the rejection reason is visible to the employee" depends on mokosh-server exposing rejection_reason in a response DTO (TimeEntryResponse / TimesheetSummaryResponse never return it today); the reason is captured and persisted by the reject endpoint, but surfacing it on the employee page is a backend follow-up.

#MAPPS-194

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-apps!207
No description provided.