09 — User Behaviour (Staff Module)
- 1. Browse & search behaviour
- 2. Create behaviours
- 3. Edit behaviours
- 4. Deactivate behaviour (destructive)
- 5. Catalog behaviours (departments/designations)
- 6. Status & error behaviours (all screens)
- 7. Analytics events
(proposed)(00-shared/10 §8 naming)
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
qparam 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;
StaffCreatedfans out in-app (event-queue-map.ts:34). Never claim an email was sent — the emails worker has noStaffCreatedhandler (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 toinactive/on_leavekeeps the record (unlike deactivate). - Metadata editor: additive key/values; empty object omitted from the PATCH
(proposed). - Concurrent-edit awareness:
versionexists 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 oldemployeeNumberremains blocked by the unique indexstaff.schema.ts:57). - Rejected path: user without
staff.deletesees no deactivate action (client mirror ofpermissions.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
leveland departments by name: client-side(proposed).
6. Status & error behaviours (all screens)
AppErrorStateper 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.