# State Management

> State conventions for server-rendered JSP pages.

---

## Overview

This project does not use React/Vue state libraries or SPA stores. State should
flow through the Servlet/JSP request cycle unless a future explicit decision
changes the frontend architecture.

---

## State Categories

- Request attributes: page data, validation errors, form echoes, table rows,
  reports, and short result messages for a single render.
- Session attributes: authenticated user identity, role, permission summary,
  and short-lived flash-style messages when redirects are used.
- Database state: books, categories, readers, borrowing records,
  administrators, permissions, and logs stored in MySQL through services/DAOs.
- Form state: submitted by browser forms to Servlets and re-rendered from
  validated request attributes on failure.

---

## Rules

- Keep business state in MySQL, not hidden fields or long-lived browser state.
- Keep permission decisions server-side.
- Use redirects after successful mutations such as create/update/delete,
  borrow, return, renew, and permission changes.
- Do not add Redux, Pinia, client caches, or SPA routing state unless the
  developer explicitly introduces that stack later.

---

## Scenario: Dashboard Workbench Request Contract

### 1. Scope / Trigger

- Trigger: the authenticated workbench spans Servlet request attributes,
  service-derived report/catalog/borrowing data, and role-specific JSP display.
- Route: `GET /dashboard`.
- JSP path: `WEB-INF/jsp/dashboard.jsp`.

### 2. Signatures

- Servlet: `DashboardServlet.doGet(HttpServletRequest, HttpServletResponse)`.
- Services used for page data:
  - `BookService.listCategories()`.
  - `BookService.searchBooks(new BookSearchCriteria())`.
  - `ReaderService.searchReaders(new ReaderSearchCriteria())` for staff reader
    totals.
  - `ReportService.loadReportCenter(AuthenticatedUser actor)` for
    administrator/librarian users.
  - `BorrowingService.searchRecords(actor, new BorrowRecordSearchCriteria())`
    for administrator/librarian users.
- Request attributes:
  - `currentUser: AuthenticatedUser`.
  - `categories: List<BookCategory>`.
  - `dashboardBooks: List<Book>`.
  - `dashboardMetrics: List<DashboardMetric>`.
  - `reportCenter: ReportCenter` for staff users when report loading succeeds.
  - `dashboardBorrowRecords: List<BorrowRecord>` for staff users.
  - `errorMessage: String` when a service returns a safe failure.

### 3. Contracts

- Workbench values must come from request attributes populated by the Servlet;
  JSP must not embed operational sample rows, fixed dates, or fake totals.
- Staff metrics use `ReportCenter` values derived from `books` and
  `borrow_records`, plus reader totals from `ReaderService`; reader fallback
  metrics may derive from `dashboardBooks`.
- Popular ranking, overdue rows, and borrowing rows render only real service
  results and show empty states when lists are empty.
- Category filters render from `categories`, the same source used by catalog and
  book-management pages.
- Role-gated sections stay in JSP conditionals based on `sessionScope.userRole`;
  staff-only data is not requested for reader users.

### 4. Validation & Error Matrix

- Category load failure -> `categories` is an empty list and `errorMessage` is
  set.
- Book search failure -> `dashboardBooks` is an empty list and `errorMessage`
  is set.
- Reader total load failure -> staff metrics fall back to another real
  service-derived metric and `errorMessage` is set.
- Staff report load failure -> report-backed sections show empty states and
  `errorMessage` is set.
- Staff borrowing search failure -> `dashboardBorrowRecords` is an empty list
  and `errorMessage` is set.
- Empty service result -> render a stable empty state, not hard-coded fallback
  sample data.

### 5. Good/Base/Bad Cases

- Good: a librarian opens `/dashboard` and sees report-backed metrics, current
  borrowing rows, overdue rows, popular ranking, and real book rows.
- Base: no borrow records exist; the workbench keeps the layout and shows empty
  states for ranking, borrowing, and overdue panels.
- Bad: `dashboard.jsp` contains names, book IDs, 2024 dates, or counts that do
  not come from request attributes.

### 6. Tests Required

- Run Maven compile/test for Servlet and JavaBean contract checks.
- Run standalone service checks covering report, borrowing, catalog/book, and
  permission policy behavior when available.
- Scan `dashboard.jsp` for static sample names, fixed dates, and decorative
  sample-only values after dashboard changes.
- Verify staff and reader role conditionals still show only the intended
  sections.

### 7. Wrong vs Correct

#### Wrong

```text
dashboard.jsp -> hard-coded metric "12,586" and fixed rows like "L20240521001"
```

#### Correct

```text
dashboard.jsp <- DashboardServlet <- ReportService/BookService/ReaderService/BorrowingService
```

---

## Page Scripts

Small JavaScript can improve interaction, such as confirm dialogs or local form
helpers, but server-side validation and service-layer rules remain mandatory.
