Skip to content

Screens: home, requests and handout

Conventions for every staff screen: the app shell from §2, a 36 px gutter, content max-width 1120 (wider pages such as Inventory and Reports may go full width), and a PageHeader from P2 or P3. “Primary” means the single filled button. States: Loading = skeleton in the final layout shape (never “Loading…” text alone); Error = an inline error block in place of the content region with “Couldn’t load X. Try again.” and a Retry button; Empty = P17 dashed card.

Mobile defaults (<768): stat grids become 2 columns; the activity rail drops below the main column, limited to 3 items with “See all”; row cards keep the chip and stack the right slot under the meta; header actions collapse to the primary plus an overflow “⋯”; underline tabs scroll horizontally with the active tab scrolled into view; drawers open full screen.

S1. Staff Home / Dashboard (dashboard) ← R1 + R2

Section titled “S1. Staff Home / Dashboard (dashboard) ← R1 + R2”

Layout: L1 AppShell + L2 DashboardLayout. The slots are filled as follows: header = date eyebrow, “Dashboard” h1 (greeting as eyebrow), Quick add primary; callout = the top-severity alert; progress = SetupChecklist; stats = the top 4 tiles; overflowStats = the remaining tiles; main = [Coming up]; rail = audit or notifications activity.

Wednesday, 14 October
Good morning, Priya ( View public page ↗ ) [■ + Quick add ▾]
┌ ! 3 loans are overdue. Remind borrowers or record a return. Review overdue → ┐ (only if >0)
└─────────────────────────────────────────────────────────────────────────────────────┘
┌Pending requests┐┌Ready for handover┐┌Overdue loans┐┌Bookings to approve┐ ← max 4 "needs action"
│ 4 ││ 2 ││ 3 ││ 1 │
└────────────────┘└──────────────────┘└─────────────┘└───────────────────┘
Coming up Recent activity
┌OCT┐ Meera Nair returns 3 items Due tomorrow (Remind) (PO) Priya accepted request
│15 │ Request #1042 · Arduino kit ×2… #1042 · 2 min ago
┌OCT┐ Laser cutter induction 12 / 16 going (DP) Dev returned Multimeter
│16 │ Event · 6:30 PM · Main hall · 1 hr ago
┌OCT┐ Woodshop bench booked Awaiting approval …
│17 │ Booking · 10:00–12:00 · Sana Khan (Review) See all activity →
Everything else ▸ (disclosure: remaining non-zero tiles as a compact 2-col list)
[ Setup checklist card — only while incomplete, above "Coming up" ]
  • Data: the existing /admin/makerspace/{id}/dashboard counts. “Coming up” merges three existing endpoints: active loans ordered return_due_at (next 5 due), upcoming events (useEvents, if the module and permission allow) and pending/upcoming bookings. Activity comes from /admin/audit-logs?makerspace=… (page size 6) when canViewAudit, otherwise from the notification inbox, otherwise the rail is hidden and the main column goes full width.
  • Stat cards: pick up to 4 tiles by priority: those with actionNeeded && value>0 first (danger tones, then warn), then fill with in-flight counts. All other permitted tiles move to the “Everything else” disclosure. This keeps all 17 reachable without the current wall of tiles. Each card is a link (existing dashboardHref). The tone shows on the number, never as a fill (aligns with the current rest style).
  • Callout: at most one, chosen by severity: overdue loans, then failed emails, then problem reports, then maintenance overdue. It has an action link.
  • Primary: “Quick add” with a menu of the existing useQuickCreate targets (item, event, booking) the actor can use. If only one is permitted it becomes a direct button. If none, no primary.
  • SetupChecklist becomes a progress card (“Set up Space Works · 4 of 7 done”, a bar, the next step as a link) placed above “Coming up”. It is dismissible once complete.
  • Empty: “Nothing needs you right now. New requests and due-backs will show up here.” Loading: 4 card skeletons plus 3 row skeletons. Machine scope (scope_mode:"machine"): the cards use machine tiles and “Coming up” shows maintenance due and prints ready.
  • The panel heading “Dashboard” is a test pin. Keep an h1 with the visible text “Dashboard” and the greeting as the eyebrow, or update the pin deliberately in Phase 4. Recommendation: h1 “Dashboard” with the greeting above it.

S2. Requests list (requests) ← R2 (tabs + rows) + R8 (inline actions)

Section titled “S2. Requests list (requests) ← R2 (tabs + rows) + R8 (inline actions)”

Layout: L3 ListLayout. The slots are filled as follows: header = “Requests”, with the subtitle and a conditional primary; tabs = Pending / Ready / On loan / History with counts; filters = search plus sort and saved views; body = rows (ListRow with date/avatar chip and an inline next step); empty/filteredEmpty per tab; pagination per queue; detail = S3 drawer.

Requests ( Export ) [■ Start handover ]*
Borrow requests from members, from review to return.
Pending 4 │ Ready 2 │ On loan 7 │ History [ Search name, email, purpose ⌕ ] [Sort ▾] [Views ▾]
━━━━━━━━━
┌ (MN) Meera Nair ⏱ Requested 2 h ago (Pending) [ Review ] ⋯ ┐
│ #1042 · 3 items · Arduino kit ×2, Multimeter ×1 · "Robotics club demo" │
└─────────────────────────────────────────────────────────────────────────────────────────────┘
┌OCT┐ Dev Patel (Ready tab) Box not assigned yet [■ Start handover ] ⋯ ┐
│15 │ #1039 · 1 item · Soldering station · due back 22 Oct │
┌OCT┐ Sana Khan (On loan tab; chip = due date, band red if overdue) Overdue 2 days [ Return ] ⋯

* The header primary is shown only on the Ready tab, and only when exactly one request is ready (it opens it). Otherwise there is no header primary and the per-row action carries it.

  • Tabs (P8) map to the existing queries: Pending = pending-requests (hidden for guestOnly), Ready = accepted-requests, On loan = active-loans, History = request-history. Counts come from each query’s count. The three live queries already run together today, so showing their counts is free; History shows no count. URL: extend the existing queue list-state value to pending|accepted|active|history (frontend only). The default tab is the first non-empty of Ready (handout-only) or Pending (others).
  • Row (P6 adapted): chip = requester avatar on Pending, due-date chip on Ready and On loan (red band and “Overdue n days” when past due; the word is always present). Title = requester. Meta = #id · n items · first two items · "purpose" with a “+n more” overflow. Status pill. One inline next step: Pending → “Review” (opens detail; Accept/Reject live there), Ready → “Start handover” (guided wizard), On loan → “Return” (guided return). Shelf location shows in the detail only (staff-only, but it adds noise to the row).
  • “⋯” row menu: Set due date, Renew (when loans.renewals), View timeline (when canViewAudit), View issue/return photo(s), Copy link.
  • The StatusStepper moves out of the row into the detail drawer (rows stay 82 tall).
  • Empty per tab: Pending: “No requests waiting for review.” Ready: “Nothing to hand over. Accepted requests land here.” On loan: “Nothing is out on loan.” History: “Returned and closed requests will appear here.”
  • Search empty: “No requests match “x”. Clear search” (link).
  • Error: inline block per tab with Retry. Loading: 4 row skeletons (RequestListSkeleton restyled).
  • Mobile: rows stack; the inline action becomes a full-width button at the bottom of the card (44 tall).

S3. Request detail + issue/return flow ← R7 (detail header, at-a-glance) + R8/R28 (scan workspace)

Section titled “S3. Request detail + issue/return flow ← R7 (detail header, at-a-glance) + R8/R28 (scan workspace)”

Layout: the detail is L4 DetailLayout presentation="drawer". The slots are filled as follows: back = Requests; identity = requester avatar; title = “Request #id”; status; meta; tabs = Overview / Evidence / Timeline; main = items plus stepper; aside = At a glance; footer = the status-driven primary. The handover is L7 FlowLayout presentation="task" with 5 steps; work = camera, borrower card, item steppers or evidence tile; result = the success card.

Detail opens as a 640 px right drawer over the list, deep-linkable with ?request=<id> (new param, like Events’ ?event=). Full screen on mobile.

← Requests ✕
(MN) Request #1042 (Ready for handover)
Meera Nair · requested 14 Oct, 9:12 · due back 22 Oct
○──●──○──○ Requested · Accepted · Issued · Returned (StatusStepper)
Overview Evidence Timeline
──────────────────────────────────────────────────
Items At a glance
┌ Arduino kit ×2 Shelf B3 (QR-tracked) ┐ Purpose Robotics club demo
│ Multimeter ×1 Shelf A1 │ Contact meera@… · +91…
└────────────────────────────────────────────────┘ Box Not assigned
Accepted by Priya (Space Manager)
─────────────────────────────────── sticky footer ─────────────────────
( Set due date ) [■ Start handover ]
  • Footer primary by status: pending → “Accept…” (opens the accept-quantities modal; Reject as an outline secondary; Set due in “⋯”); accepted → “Start handover”; issued or partially_returned → “Record return”; terminal → none.
  • Evidence tab: issue and return photos as thumbnails loaded on demand through the existing signed-URL fetch, labelled with type, actor and time, never as public URLs. Empty: “No photos yet. The issue photo is taken during handover.”
  • Timeline tab: RequestTimelineBlock as an activity list (P12 style) when canViewAudit.
  • Damaged, missing and to-fix outcomes show as a danger-tinted advisory under Items.

Handover flow (HandoverWizard, issue and return). One component for both. It replaces the side-by-side “Assign + issue” modal and “Guided issue” button, which are two buttons for one job. The non-guided AssignIssueModal / ReturnRequestModal / IssueDialog / ReturnDialog become a “Compact view” toggle of the same flow (all steps on one scroll page) for experienced staff. Hard rules are unchanged: box QR, borrower check, items and assets, an issue photo (mandatory), a return photo plus a remark (mandatory), the kit checklist and the receipt.

Desktop: full-screen task mode (no sidebar), 2 columns
┌ Issue request #1042 · Meera Nair ─────────────────────────────── ( Cancel ) ┐
│ ① Scan box ✓ BOX-0042 │ │
│ ② Check borrower ✓ │ ┌──────── camera (dark, r16) ────────┐ │
│ ③ Items 2 / 3 assets │ │ ⌜ ⌝ │ │
│ ④ Photo & remark ● required │ │ Hold the asset QR in the frame │ │
│ ⑤ Receipt │ └────────────────────────────────────┘ │
│ │ Can't scan? [ Type the QR code ] (Check)│
│ │ Scanned ✓ ARD-0091 ✓ ARD-0092 Remove │
│ │ ( Back ) [■ Next ] │
└────────────────────────────────┴────────────────────────────────────────────┘
  • Left rail: 5 steps with state (done ✓ plus its captured value, current ●, locked). Done steps are clickable to go back. Mobile: the rail becomes a top progress bar with “Step 3 of 5 · Items” and the camera fills the width.
  • Step 1 Scan box: the camera block (P21 and P29) starts on entry because scanning is the task. Manual entry sits beneath it. A success shows the box label inline with a green check and auto-advances after 600 ms (an announced role=status).
  • Step 2 Borrower: an identity card (avatar, name, membership status pill, waiver status), the optional member-card scan (ScanCardBox), and the confirmation checkbox “I checked the borrower against this request” (keep the wording; it is the accountability statement).
  • Step 3 Items: issue mode shows an asset counter as a progress stat (“Assets scanned 2 / 3”) with continuous scanning in the same camera block and the scanned list with Remove. Return mode shows per-item rows with three steppers (Returned / Damaged / Missing) and a live “of n remaining” check (reuse QuantityInput validation copy).
  • Step 4 Photo & remark: the evidence tile (see §5) is large (16:9 placeholder, “Take photo” primary, “Upload from device” link). After upload it shows the thumbnail, “Photo #182 attached” and “Retake”. The remark field is labelled “Return remark” with a “Required” chip in return mode and “Remark · Optional” in issue mode. The kit checklist follows. The step footer primary reads “Confirm issue” / “Confirm return” and is disabled with the reason (“Add the return photo and a remark to continue.”), never silently disabled.
  • Step 5 Receipt: a full-panel success result (P29 green card): “Issued to Meera Nair”, the summary (box, items, photo #, time), “Print receipt” (outline) and “Done” (primary). No Undo. Handover records are immutable and audited, so the summary-before-confirm in step 4 is the safety net.
  • Partial-failure copy is kept verbatim in intent (“Box assigned, but issue failed: … The request still needs the issue step; retry with the assigned box.”) and shown as a danger callout above the footer.
  • Escape: “Cancel” is disabled while saving. Closing with captured evidence asks “Leave handover? The uploaded photo stays unattached and will be cleaned up.” Copy needs owner sign-off: the abandoned-upload cleanup is default-off, so the claim must match the deployment.

S4. Direct handout (direct) ← R2 list + S3 flow

Section titled “S4. Direct handout (direct) ← R2 list + S3 flow”

Layout: L3 ListLayout. The slots are filled as follows: header = “+ New handout” primary; tabs = On loan / Returned / Claim codes; body = rows with inline Return. New handout and Return are L7 FlowLayout (4 and 3 steps).

Direct handout [■ + New handout ]
Lend tools straight from the shelf, without a request.
On loan 5 │ Returned │ Claim codes
┌OCT┐ Arjun Rao Due 20 Oct [ Return ] ⋯
│20 │ Handout #88 · Multimeter, Probe set · 2 tool QRs · by Priya
  • “+ New handout” opens the guided DirectHandoverWizard in task mode (borrower card, then tools, then photo, then receipt; the same shell as S3). The always-visible inline issue form currently on the page moves into that flow’s “Compact view”. The page itself becomes the list of direct loans with inline Return (the existing DirectLoanReturnModal restyled as the S3 return steps).
  • The “Claim codes” tab hosts MemberClaimCodes.
  • Empty: “No tools are out on direct handout. Start one with New handout above.”
  • Mobile: the primary becomes a full-width sticky bottom button above the bottom tab bar (handout console).

Part of Space Works UX spec, published from docs/ux-spec.md. Edit it there.