Skip to main content
  1. Projects/
  2. Maintenance Log/

Maintenance Log Frontend - Fourteenth Week: Manager/Admin Flows, Create Pages, and Session Expiry Handling

Jesper Andersen
Author
Jesper Andersen
Table of Contents
Maintenance Log - This article is part of a series.
Part : This Article

Devlog Week 14: Manager/Admin Flows, Create Pages, and Session Expiry Handling
#

This entry covers the manager/admin-facing workflows (create pages and domain admin actions), and ends with a centralized error-handling + session expiry (token expiration) flow to keep UX consistent across the app.

What Changed
#

  • AssetAdminActions extracted as a domain-specific admin component (separate from employee AdminActions)
  • Inline confirmation pattern added for destructive actions (“Are you sure?” → Yes/Cancel)
  • CreateAsset page added and protected behind MANAGER+
  • CreateEmployee page added and protected behind MANAGER+ with role options derived from the current user’s role
  • Drawer menu updated to show manager routes conditionally and replace placeholder routes
  • Centralized HTTP error handling added to apiRequest() with status-based messaging
  • Session expiry redirect flow implemented using sessionStorage
  • Network error handling improved (fetch TypeError mapped to a user-friendly message)

AssetAdminActions: Intentional Separation + Inline Confirm UX
#

There are now two admin-action components:

  • AdminActions (employee/admin operations)
  • AssetAdminActions (asset/admin operations)

Even though there is some similarity, this is intentional separation by domain, not accidental duplication. Keeping them separate avoids coupling unrelated concerns and makes future asset-specific actions easier to extend without affecting employee logic.

The component uses an inline confirmation pattern:

  • first click enters a confirming state
  • UI swaps to “Are you sure?” with Yes/Cancel

In AssetDetail, the component is rendered with key={asset?.id} so it remounts when the asset changes. That resets the confirmation state automatically.

Updates are applied optimistically through an onAssetUpdated callback so the detail page reflects changes immediately.

CreateAsset: MANAGER+ Route + Practical Defaults
#

CreateAsset is a separate page protected behind MANAGER+.

  • fields: name, description, active
  • active defaults to true as a sensible UX default
  • on success, it navigates to the new asset detail page if the API returns an id (fallback to asset list otherwise)

CreateEmployee: Role-Restricted Options (Defence in Depth)
#

CreateEmployee is also MANAGER+ and posts to the backend POST /auth/register endpoint.

Role options are computed with useMemo based on the authenticated user’s role:

  • managers can only create AUTHENTICATED and TECHNICIAN
  • admins can create all roles

This is frontend enforcement of a backend gap (defence in depth): managers should not be able to create admins, even if the backend does not validate that properly yet.


DrawerMenu Updates: Real Routes + Role-Conditional Links#

Manager+ routes are now conditionally rendered via a canViewManagerRoutes flag.

  • links added for Create Asset and Create Employee
  • placeholder links replaced with real routes

This keeps navigation aligned with permissions and avoids dead-end pages.


Centralized Error Handling (Last): Consistent Messages + Session Expiry
#

To make failures predictable, error handling was centralized in the shared API layer.

HTTP Error Mapping in apiRequest
#

A readBackendErrorMessage helper reads JSON error payloads and extracts a message field when available.

apiRequest() then maps statuses into consistent UI-facing errors:

  • 401 → redirect to login with a “session expired” message
  • 403 → permission denied
  • 404 → resource not found
  • 409 / 400 → show backend message (validation/conflict)
  • 503 → service unavailable
  • >= 500 → generic server error
  • fallback → backend message or a generic error including the status code

Session Expiry / Token Expiration Flow
#

To handle expired tokens cleanly (and avoid half-broken state):

  • a redirectToLoginWithSessionExpiredMessage() helper performs a full page reload via window.location.assign("/login")
  • sessionStorage is used as a simple message between the redirect and the login page
  • the redirect helper guards against loops when already on /login
  • shared constants (SESSION_EXPIRED_MESSAGE_KEY, SESSION_EXPIRED_MESSAGE) live in a dedicated sessionMessages.js module
  • Login.jsx reads the flash message on mount and clears it immediately after displaying

Network Error Handling
#

A TypeError thrown from fetch is treated as a network/CORS/unreachable-backend scenario, and is converted into a user-friendly “Unable to reach server” message.


Up Next
#

  • Small refactors to reduce repetition (where it stays intentional by domain)
  • Identify any backend validation gaps that should be enforced server-side
  • Add quick UX polish passes (empty states and copy consistency)
Maintenance Log - This article is part of a series.
Part : This Article

Related

Maintenance Log Frontend - Twelfth Week: User Profiles, Employee Admin Actions, and Form Patterns

Devlog Week 12: User Profiles, Employee Admin Actions, and Form Patterns # This entry covers the employee-facing parts of the UI: profile views, edit flows, admin actions, and the form patterns used to keep components maintainable. What Changed # UserProfile supports both “me” and viewing other employees via dynamic route params Profile page extracted into focused subcomponents: EditProfileForm, AdminActions, PasswordChangeForm Form handling uses a mix of controlled inputs and a FormData approach (when appropriate) useEffect race-condition prevention via an ignore flag to avoid setting state after unmount Admin-only employee actions (deactivate/reactivate) gated by role and disallowed on own profile User Profile: “Me” vs “Other Employee” # The profile route supports multiple entry points:

Maintenance Log Frontend - Eleventh Week: Assets, Logs, Filtering, and Creating Maintenance Entries

Devlog Week 11: Assets, Logs, Filtering, and Creating Maintenance Entries # This entry focuses on the asset/log workflow: fetching real data from the API, filtering lists, displaying asset details, and adding log creation behind role checks. What Changed # AssetList now fetches from the real backend API Active/inactive filtering implemented via a reusable Select component AssetDetail fetches asset + logs in parallel using Promise.all Status and task type filters wired to server-side filtering “Create log” is role-gated (TECHNICIAN+) and also hidden for inactive assets CreateLog includes client-side validation and prevents double-submit CSS Modules adopted for scoped styling Asset List: Fetch + Filter Pattern # AssetList implements a reusable pattern used elsewhere in the frontend: