Skip to content

Screens: machines, events, bookings, reports and audit

S10. Machines ← R1 cards (index), R7 detail header + tabs (type page), R5 rows (machine detail)

Section titled “S10. Machines ← R1 cards (index), R7 detail header + tabs (type page), R5 rows (machine detail)”

Layout: the index is L3 ListLayout. The slots are filled as follows: body = rows, rendered as a card grid via the ListRow card variant; callout = overdue maintenance. The type page is L4 DetailLayout (page, identity = type icon). Its tabs = Machines / Service queue / Consumables / Certifications / Settings, with Machines-tab main = an embedded table and status filter tabs. The machine detail is L4 DetailLayout presentation="drawer" width=720, with danger = Retire.

Index (/admin/machines):

Machines [■ + Add machine type ]*
24 machines across 5 types · 3 running · 1 in maintenance
┌ ! Maintenance is overdue on 2 machines. Review → ┐ (only if >0)
┌[🖨] 3D printers ─────────┐ ┌[⚡] Laser cutters ───────┐ ┌ + Add machine type ┄┄┐ (dashed, if allowed)
│ 8 machines · 3 running │ │ 2 machines · idle │
│ 4 jobs in queue (Review) │ │ Next maintenance 3 Nov │
└───────────────────────────┘ └──────────────────────────┘
Type settings ▸ (MachineTypesPanel, shared consumables, delegated recipients) — disclosure

* when canConfigureMachineTypes.

Type page (/admin/machines/12-3d-printers, an existing subpath):

← All machine types
[🖨] 3D printers ( Public page ↗ ) [■ + Add machine ]
8 machines · 3 running · 1 maintenance
Machines 8 │ Service queue 4 │ Consumables │ Certifications │ Settings
Machines tab: table rows [img] Name / model · location | (Running) pill | 312 h | ⋯ + status filter tabs (All · Idle · Running · Reserved · Maintenance · Offline)
  • Map the stacked sections to tabs: Machines (list plus MachineCreateForm moved into the “+ Add machine” modal), Service queue (PrinterServiceConsole / MachineServiceConsole), Consumables (the pool form and list), Certifications (CertificationsPanel), Settings (MaterialCataloguePanel, MachineReminderPolicy). The tab state uses a query param ?view= (frontend only). Tabs show only when their gate holds today.
  • Machine detail (MachineDrawer, 720 px drawer):
[img] Prusa MK4 #2 (Running) · 3D printer · 312 h total
[■ Mark idle ] ( Log maintenance ) ⋯ (Retire…)
Overview Operators Consumables Usage Maintenance Documents Errors Warranty
Overview: stat cards (Usage hours · Jobs this month · Next maintenance · Open errors), then settings rows (photo, details, public detail)
┌ Retire machine ─ Takes it out of service and off the public page. ( Retire… ) ┐ (danger, can_retire)
  • Replace the button-styled tablist with P3 underline tabs (keep role=tablist and wrapping, so every tab stays visible; the current comment about clipping still applies). The header primary is the most common status transition the actor may perform (from OverviewTab’s status block).
  • Empty: “No machines are registered for this type. Add the first one with Add machine.” Keep the “requires a successful load” rule from MachineTypePage.

Layout: L3 ListLayout. The slots are filled as follows: header = greeting eyebrow, “New series” secondary, “+ New event” primary; callout = collaboration invites or door-ready; stats = 4; tabs = Upcoming / Drafts / Past / Series; body = date-chip rows; rail = recent registrations (when data exists). New event and New series are L6 FormPageLayout, with preview = the public event card.

Good morning, Priya
Events ( New series ) [■ + New event ]
┌ ! Laser workshop is tomorrow. Download the guest list for offline check-in. Prepare check-in → ┐
┌Upcoming 3┐┌Going 46┐┌Awaiting approval 2┐┌Drafts 1┐
Upcoming │ Drafts 1 │ Past │ Series 2 Recent registrations
date-chip rows: right slot = "12 / 30 going" bar │ "Finish & publish" pill │ "No guests yet · Share"
  • Remove the always-open create form from the list page. “+ New event” opens a create page (R3 layout: form left, public event card preview right) and “New series” opens the series variant. The useQuickCreate("event") hook opens the same page.
  • CollaborationInbox and EventSeriesCollaborationInbox collapse into one callout when invitations are pending (“2 venues invited you to co-host. Review →”) that opens a drawer. No callout when empty.
  • Stat cards use registration_counts summed over the loaded page only if the backend has no aggregate. Flag: prefer a server count; otherwise show only Upcoming and Drafts (exact from list counts) and omit the rest rather than show page-local sums.
  • Rail: latest registrations if an endpoint exists; otherwise hide the rail.
  • The table becomes date-chip rows. Status words: Draft (grey, dashed row), Published (green), Cancelled (red word pill), Completed (grey).
  • Empty (no events): dashed “+ New event” placeholder row: “Your events will appear here.”

Layout: L4 DetailLayout (page). The slots are filled as follows: identity = date chip; actions.primary = status-driven (with targetsTab="checkin" so it hides on that tab); tabs = the 7 tabs below; Overview aside = At a glance plus the CTA card; Settings tab main = SettingsRows; danger = Cancel event. The series detail uses the same layout with an icon identity.

EventDrawer becomes a full detail page reached by ?event=<id> (the param already exists). It is too dense for a drawer: 9 stacked panels.

← All events
┌OCT┐ Laser cutter induction ( View page ↗ ) [■ Open check-in ]
│16 │ (Published) Public · Tomorrow, 6:30 PM · 12 / 16 places
Overview Registrations 14 Check-in Tickets & invites Feedback Team Settings
Tab Content (existing components)
Overview Stat cards (Going n/cap with bar · Waitlist · Awaiting approval · Invites sent), “Latest registrations” list (5 rows + “All registrations →”), an “At a glance” card (When, Where, Who can join, Price), and the door-ready CTA card when tomorrow or today and offline check-in is enabled.
Registrations EventRegistrationRoster as a P14 table with status pills (Going, Waitlist, Pending) and inline Approve / Decline… for pending; EventRegisterMember as “+ Add registration” (outline).
Check-in The R8 layout: progress stat plus offline callout (OfflineCheckInOperator), camera and Start scanning (EventCheckInScanner), find a guest, toggles, Recent check-ins with inline Undo only if the backend supports reversing a check-in (otherwise omit; do not fake it), and the door-station card (EventStationSettings).
Tickets & invites EventTicketsPanel, EventPromosPanel, EventInvitesPanel, each a section; shown only for enabled ticketing_features.
Feedback EventFeedbackPanel and responses; certificates (EventCertificateActions).
Team EventOrganizers, EventCollaborators.
Settings Image (ImageUploader), EventFields as settings rows, EventCategoriesField, series overrides (“Reset to series value” per field), Discard/Save; lifecycle at the end: Complete (outline) and a danger card “Cancel event… Registrants are notified and registration closes.”
  • Header primary by status: draft → “Publish…” (confirm, because it notifies the public); published → “Open check-in” (hidden on the Check-in tab); completed → “View feedback”. Cancelled or completed: a read-only banner “This event is completed. It can’t be edited.”
  • Series (EventSeriesDrawer) gets the same page treatment per R10: upcoming-date cards, details, a “Who can join” chip radio, agenda, and the “Delete series…” danger zone.

Layout: L3 ListLayout. The slots are filled as follows: stats; tabs = Requests / Upcoming / Spaces (or Spaces only in the minimum variant); body = rows. The space detail is L4 DetailLayout (page). “+ New space” is L6.

Bookings ( + New booking ) [■ + New space ]
┌Awaiting approval 1┐┌Today 4┐┌This week 19┐┌Spaces 6┐ ← approval count from dashboard; others only if available
Requests 1 │ Upcoming │ Spaces 6
Spaces tab rows: [tile] Woodshop bench · Workshop · (Staff approval) (Public) (Active) · "3 today" ⋯
  • Today the page lists spaces only; booking requests live inside each space’s BookingDrawer. Minimum change: the spaces list as P6 rows with pills replacing the 5-column table, and the “Awaiting approval” stat linking to the first space with pending requests. Better (needs a cross-space bookings list endpoint, so flag it): the Requests and Upcoming tabs.
  • The space detail opens as a page (R7 pattern) with tabs Calendar, Requests, Settings (the BookableSpaceForm rows) and Danger (deactivate).
  • Empty: “No bookable spaces yet. Create one to start taking bookings.”

S14. Reports (reports) ← R6 (form card) + P4

Section titled “S14. Reports (reports) ← R6 (form card) + P4”

Layout: L4 DetailLayout (page) with asideSide="start". The slots are filled as follows: aside = the grouped report list; title = the selected report; actions = Export primary and Schedule secondary; main = filter bar, stats, chart and table. No back and no identity: this is the one sanctioned L4 variant without them.

Reports ( Schedule… ) [■ Export ▾ ]
Operations reporting for Fab Lab Kochi.
┌ Report list (240) ────────┐ Loan throughput
│ LENDING │ [7 days | 30 days | Quarter | Custom ▾] Grain [Day ▾] ☐ All makerspaces*
│ ▣ Summary │ ┌Products┐┌Active loans┐┌Damaged┐┌Missing┐
│ Taken items Active… │ chart (existing hand SVG)
│ INVENTORY … MACHINES … │ table (OperationsReportTable) Saved views ▾ Columns ▾
│ COMMUNITY … MONEY … SYSTEM│
└───────────────────────────┘
  • Replace the 28-option <select> with a grouped left list (eyebrow group labels). Unavailable reports show as disabled rows with unavailable_reason in a tooltip and a muted “Needs Bookings module”.
  • Date presets as a segmented control plus custom inputs. Export is the primary because it is the page’s output. Schedule (ReportSchedules) opens a drawer.
  • Mobile: the report list becomes a select sheet at the top.
  • Empty data: “No activity in this period. Try a longer range.”

S15. Audit log (audit) ← R1/R2 activity rail as a full list + P14

Section titled “S15. Audit log (audit) ← R1/R2 activity rail as a full list + P14”

Layout: L3 ListLayout width="wide". The slots are filled as follows: callout = verification status (success pill, or a danger panel if broken); filters = AuditLogFilters with chips; body = rows (activity items grouped by day); pagination.

Audit log ( Export )†
Every state change in this makerspace, append-only.
(✓ Chain verified · checked 2 min ago) ← AuditVerificationStatus as a status pill/callout (danger callout if broken)
[Actor ▾] [Action ▾] [Target ▾] [Date range] Sort ▾ (AuditLogFilters as a filter bar; active filters as removable chips)
TODAY
(PO) Priya accepted request #1042 · Meera Nair 10:57 · request:1042 ▸ details
(DP) Dev uploaded return photo #182 · request #1039 10:47
YESTERDAY …

† only if an export endpoint exists; otherwise omit.

  • The row is the activity-rail sentence (actor bold, action_label, target as a link where a console route exists). The raw action key and the meta go into a “details” disclosure (monospace key–value). Keep “(some details withheld)” when redacted.
  • Group by day with sticky day headers. Use keyset-friendly “Load more” or keep the current pagination at the bottom (“Page 2 · 1,204 entries”).
  • Empty with filters: “No entries match these filters. Clear filters.”
  • No Undo or edit affordances anywhere (append-only).

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