Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

09 — User Behaviour (Staff Module)

Behavioral rules for staff screens. (proposed) = client decision; backend-derived items cite source.

1. Browse & search behaviour

  • HR opens Staff → list loads from GET /staff (page 1, limit 20 — staff.controller.ts:27-28, pagination-query.dto.ts:13-19). Skeleton ≤ 200 ms (00-shared/10 §1).
  • Search box: client-side filter with 300 ms debounce (00-shared/03 AppSearchBar); the q param is sent but ignored server-side for staff (staff.service.ts:64-76, OQ-2) — UI labels "filtering loaded results" when a filter is active.
  • Status/type chips filter loaded pages only; switching chips keeps scroll position.
  • Scroll down hides FAB, scroll up restores (00-shared/03 AppFAB); infinite scroll appends while meta.hasNext (pagination-query.dto.ts:52).
  • Pull-to-refresh resets to page 1 and bypasses cache (00-shared/06 §3.3).
  • Rows are tappable → detail; overflow menu offers View/Edit/Deactivate.

2. Create behaviours

  • "Add staff" FAB (staff.create) → SS3. User picker lists users (required — create-staff.dto.ts:5-7); a staff profile cannot exist without a user.
  • Submitting with a duplicate employeeNumber → 409 inline on the field (staff.service.ts:31-36); user edits and resubmits — no navigation loss.
  • On success: navigate to detail + snackbar; StaffCreated fans out in-app (event-queue-map.ts:34). Never claim an email was sent — the emails worker has no StaffCreated handler (email.worker.ts:25-42, OQ-6).

3. Edit behaviours

  • Edit prefills from detail; only changed fields sent (staff.service.ts:88).
  • Status dropdown exposes the full enum (staff.schema.ts:7-12): moving someone to inactive/on_leave keeps the record (unlike deactivate).
  • Metadata editor: additive key/values; empty object omitted from the PATCH (proposed).
  • Concurrent-edit awareness: version exists server-side (base.repository.ts:63, 71; base.schema.ts:29-31) but is not in the DTO (update-staff.dto.ts) — last-write-wins; client does not implement optimistic conflict UI (OQ-12).

4. Deactivate behaviour (destructive)

  • Trigger anywhere → SS5 confirm dialog; copy is honest: "removes from all lists, no undo" (base.repository.ts:68-74).
  • Confirm → DELETE → success snackbar + list refresh (row gone). 404 → "already deactivated" + refresh.
  • No restore flow — if the org misclicks, the record is gone from the UI (data survives in DB with isDeleted: true). HR must recreate (and the old employeeNumber remains blocked by the unique index staff.schema.ts:57).
  • Rejected path: user without staff.delete sees no deactivate action (client mirror of permissions.constants.ts:22).

5. Catalog behaviours (departments/designations)

  • Add/rename/recode/head assignment: same form rules as F3–F6; duplicate name → 409 inline (department.service.ts:23-25, designation.service.ts:25-28).
  • Delete confirm: warns "existing staff references will dangle" — no server guard blocks deleting a department with members (OQ-4); UI offers no member reassignment step ((proposed) mitigation: show member count in the dialog).
  • Catalog changes do not produce notifications (no events emitted — department.service.ts:19-20, designation.service.ts:22-23; OQ-10).
  • Sorting designations by level and departments by name: client-side (proposed).

6. Status & error behaviours (all screens)

  • AppErrorState per code (00-shared/06 §5): 401 refresh; 403 permission screen/action hide; 404 empty-state; 400 field errors; 409 inline; 422 n/a (no 422 producers in this module); 429 backoff; 5xx generic + requestId.
  • Offline: cached list + AppOfflineBanner; writes blocked with guidance (00-shared/06 §3.7).
  • Session expiry mid-flow: re-login preserving nav (00-shared/06 §3.6).
  • Optimistic updates: none in this module — all mutations wait for the server result (status changes included; safe per 00-shared/06 §3.5).

7. Analytics events (proposed) (00-shared/10 §8 naming)

staff.list.view, staff.list.search, staff.list.filter(status|type), staff.detail.view(id), staff.create.submit|success|duplicate, staff.update.submit|success, staff.deactivate.confirm|success, department.create.success|duplicate, department.delete.confirm, designation.create.success|duplicate, designation.delete.confirm.