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

07 — Component Library (Users Module)

Module-specific components. Shared building blocks referenced from 00-shared/03_Component_Library.md are not redefined. All components are (planned) (no client repo). Backend-derived constraints cited.


1. Module component list

ComponentPurposeBuilds on
UserListTileList row for S1AppListTile + AppAvatar + AppBadge
StatusBadgeUser status pillAppBadge
RoleChipsRole display/selectionAppChips
FilterBarSearch + status/role chipsAppSearchBar + AppChips
AvatarUploaderAvatar pick/crop/uploadAppAvatar + AppDialog
ImportWizard3-step bulk import shellAppStepper + AppProgress
CsvPreviewTableParsed-row previewtable (00-shared/04 §8 desktop)
ImportErrorListRow-numbered error tableAppListTile dense + AppBadge
TemplateDownloadButtonCSV template export (client-generated)AppButton outlined
PreferencesPanelNotification/theme controlsAppSwitch + AppRadio + AppDropdown
SelfProfileHeaderAvatar + identity headerAppAvatar + AppInfoRow
PermissionScopedConditional render/guard wrapperroute guards (00-shared/05 §9)
TypedConfirmDialogDelete/erase typed confirmAppDialog

2. UserListTile

  • Props: user, roles?, onTap, onEdit, onDeactivate, onDelete, onErase, selected.
  • Render: avatar 40 (initials fallback — 00-shared/03 AppAvatar), title = displayName (users.service.ts:62 guarantees non-empty), subtitle = email, trailing = StatusBadge + AppMenu (View · Edit · Deactivate/ Activate · Delete · GDPR erase).
  • States: selected (master-detail), loading avatar placeholder.
  • A11y: single button semantics; badge text included in summary.

3. StatusBadge

  • Maps UserStatus exactly (user.schema.ts:7-12):
StatusTokenIcon+label (never color-only, 00-shared/09 §9)
activesuccess/secondary✓ Active
inactiveneutral onSurfaceVariant outlined◌ Inactive
suspendederror/tertiary⊘ Suspended
invitedprimaryContainer✉ Invited
  • Unknown value (server could add) → neutral "Unknown" badge, no crash (forward-compat).

4. RoleChips

  • Props: roles[], onToggle, editable, loading.
  • Data: GET /rbac/roles (rbac.controller.ts:27-31) — list mode shows member roles from GET /rbac/members joined by userId (rbac.controller.ts:57-61); empty when the viewer lacks org_admin (that endpoint is role-gated :21-22) — show "—" with tooltip, never fake.
  • Selected chip = secondaryContainer (00-shared/04 §2).

5. FilterBar

  • Search: AppSearchBar, debounce 300 ms, server-side q (users.service.ts:92-99).
  • Status chip group (StatusBadge values) + role chip group: client-side filter of loaded pages with explicit caption "(planned) server filter — applies to loaded results only" (04_IA §10, OQ-9).
  • Clear-all button resets chips + query.

6. AvatarUploader

  • Flow: tap avatar → pick image (file_picker) → square-crop dialog → multipart POST /users/:id/avatar (users.controller.ts:95-102) with field name = file (FileInterceptor('file') :96).
  • Response {avatarFileId} (users.service.ts:230) — display via storage URL resolution (planned) (no URL from this endpoint; file id only).
  • States: uploading (avatar overlay spinner), error (revert + snackbar), success (HapticFeedback.lightImpact).
  • Size guidance: keep ≤ 2 MB (no backend cap in code — OQ-10).

7. ImportWizard

  • AppStepper steps: 1 Upload → 2 Preview → 3 Result (00-shared/03 AppStepper).
  • Owns BulkImportCubit state (13_State_Management.md §6); back-nav from step 2 → step 1 keeps parsed file.
  • Destructive exit (leave mid-flow) → unsaved-changes dialog (parse state only; nothing server-side pending).

8. CsvPreviewTable

  • Columns from parsed header (users.service.ts:244-247); row numbers 1-based, header = row 1 — error rows are index + 2 (bulk-import.service.ts:46 precedent) and Row N in users import refers to the physical line (users.service.ts:257) — the preview must display physical line numbers to match error strings.
  • Highlight rows flagged client-side (missing email, dup email, quotes).

9. ImportErrorList

  • Rows: physical row number (mono font, 00-shared/02 §2) + message verbatim; badge count = errors length; "Download errors" button exports row,message CSV client-side.
  • Empty state when errors.length === 0 → success check icon.

10. PreferencesPanel

  • AppSwitch × 3 (email/push/sms — update-user-preferences.dto.ts:8-12), AppRadio theme mode × 3 (light|dark|system:16-20), AppDropdown language.
  • Save = merged full object (users.service.ts:161-163 replaces wholesale).

11. PermissionScoped

  • Wrapper taking a permission string (e.g. user.delete) → hides/rebuilds subtree; route-level equivalent via permissionGuard (00-shared/11 §6).
  • Caution: server users controller currently enforces JWT only (users.controller.ts:31); RBAC guard on those routes is (planned) — the client still gates by permission so behavior is correct the day the guard lands (OQ-11).

12. Reused shared components (no new code)

AppSearchBar, AppChips, AppStepper, AppProgress, AppEmptyState, AppErrorState, AppSnackbar, AppDialog, AppBottomSheet, AppMenu, AppDatePicker, AppAvatar, AppBadge, AppListTile, AppInfoRow, AppFAB, AppTabs, AppSkeleton.


Golden-test expectation (00-shared/03 §G)

UserListTile, StatusBadge (4 states), RoleChips, ImportErrorList, PreferencesPanel at 3 sizes + light/dark.