Skip to content

Staff Entity Detail Page Redesign — Design

This is the design / rationale / wireframe doc. For the canonical contract — invariants, scope, component shapes, content maps, sheet behavior, permissions, tables, MG ID system, action endpoints — see spec.md. When the two disagree, spec.md wins.

Drift notes (resolved by spec.md, not yet rewritten here):

  • Entity scope is all of apps/web/src/app/(app)/staff/, not just the original 6.
  • Reservation is one detail page that branches on ReservationType (MONTHLY / HOURLY / TOUR), not a Lockout-only page.
  • User now has an MG ID (USR{seq}) — schema change is a backend prereq.
  • MG ID format is dashless (RSV22, AST42), not RSV-22 / AST-42 as wireframes show.
  • Read-only / financial entities (Payment, Charge, Ledger, Lock, Studio Reference) use the same shell with no edit affordances.
  • Sheets anchor right on desktop, bottom on mobile with drag handle + swipe-down dismiss.
  • Save flow is invalidate-and-refetch; dirty-state guard fires on every dismiss vector; last-write-wins concurrency with Updated by in System.
  • Every detail page gets an Activity section (audit-log powered, Load more paginated) as the last main-column block.
  • Per-row ... menus come from a single entity-bound rowActions(entity, viewerRoles) function shared by detail-page and list-page tables.
  • "Inline-edit affordances" phrase removed from the contract — sheets + actions menu only.
  • View in Stripe → uses a single shared stripeDashboardUrl(resource, id) helper (single platform account; only mode varies).
  • Actions whose backend endpoints don't exist (Pause billing, Send payment link, Refund, Resend receipt, Convert to lockout, Duplicate, Export resources) are stripped from launch menus and tracked in spec's Future actions backlog.

Problem Statement

All staff entity detail pages (reservations/lockouts, users, locations, resources, assets, organizations) share the same poor UX/UI pattern:

  1. Mixed edit/display modes - Forms mix editable HeroUI input fields with read-only LabeledValue displays, making it impossible to scan what's changeable
  2. No visual hierarchy - Everything dumped into flat tabs with no grouping or structure
  3. Typography chaos - Inconsistent label styles (LabeledValue uses uppercase 12px labels, HeroUI inputs use floating labels, helper text scattered as standalone <p> tags)
  4. No design system - Each form evolved organically with different patterns
  5. Massive form components - Single forms handle both create and edit modes, reaching 1700 lines (LockoutForm)

Current Architecture

All staff entity pages follow this pattern:

  • Server component ([id]/page.tsx) fetches data
  • Client component (EditEntityPage.tsx) handles mutations
  • Form component (EntityForm.tsx) renders React Hook Form with Zod validation
  • StaffFormLayout wraps forms with tabs (edit mode) or stacked cards (create mode)
  • HeroUI components (Input, Select, Autocomplete, Textarea) for form fields
  • LabeledValue component for read-only fields, mixed inconsistently with form inputs
  • FormSection has 3 variants (default, card, collapsible) but edit mode always uses default (basically nothing)
  • System tab auto-generated by StaffFormLayout, but some forms also define their own system fields

Current form files and sizes:

  • apps/web/src/components/organisms/forms/LockoutForm.tsx (~1700 lines)
  • apps/web/src/components/organisms/forms/ResourceForm.tsx (~1060 lines)
  • apps/web/src/components/organisms/forms/LocationForm.tsx (~890 lines)
  • apps/web/src/components/organisms/forms/AssetForm.tsx (~750 lines)
  • apps/web/src/components/organisms/forms/UserForm.tsx (~440 lines)
  • apps/web/src/components/organisms/forms/OrganizationForm.tsx (~180 lines)

Supporting files:

  • apps/web/src/components/molecules/forms/StaffFormLayout.tsx - shared layout wrapper
  • apps/web/src/components/molecules/forms/FormSection.tsx - section container
  • apps/web/src/components/atoms/forms/LabeledValue.tsx - read-only display
  • apps/web/src/components/molecules/forms/FormFieldGroup.tsx - side-by-side field layout

Solution: View/Edit Separation Pattern

Design Inspiration

Inspired by Stripe's dashboard pattern, adapted for Metrognome's simpler needs:

What Stripe does:

  • Detail pages are read-only display
  • Primary CTA button in header ("Edit product", "Update subscription") opens a drawer/sheet
  • Actions menu (...) for less common operations (cancel, pause, etc.)
  • Two-column layout: main column for activity/tables, sidebar for details/metadata
  • Small edit pencil () on sidebar sections for focused edits
  • Sidebar collapses below main content on mobile

How we adapt it:

  • Same view/edit separation and sheet pattern
  • Same two-column layout logic
  • Simpler than Stripe (we don't have API logs, events, tax calculations)
  • Our entities have less activity data but still enough for tables (payments, reservations, placements)
  • No need to replicate Stripe's visual language - just the UX pattern

Column Content Logic

Main column = "What's happening / what's related"

  • Tables of related data (payments, reservations, resources)
  • Activity and history
  • Lists with add/remove (images, access codes, directions)
  • Things you scan through or work with

Sidebar = "What it is / who it belongs to"

  • Entity properties grouped into sections
  • Related entity links (customer, location)
  • IDs, dates, status info
  • Each section optionally editable via button

On mobile, sidebar content stacks below main content (single column).

Core Principles

  1. Display separated from edit - Detail surfaces render values as labels-and-text only; no form inputs mixed with display fields. Edits route through sheets, the actions menu, or designated inline-edit affordances.
  2. Primary edit button - [Edit X] in header row opens sheet with core editable fields
  3. Section edit buttons - Small on sidebar sections for metadata edits
  4. Actions menu - [...] for rare/dangerous actions (cancel, delete)
  5. Two-column layout - Main column for activity/lists, sidebar for details
  6. Create via sheets - List pages have [+ Add X] button that opens create sheet

Layout Pattern

┌─────────────────────────────────────────────────────────────────────────────┐
│  {EntityType} › {MG_ID}                                    [Edit {X}] [...] │
│                                                                             │
│  {Entity Name}  ● {Status}                                                  │
│  {Subtitle}                                                                 │
│                                                                             │
├───────────────────────────────────────────────────┬─────────────────────────┤
│                                                   │                         │
│  MAIN COLUMN                                      │  SIDEBAR                │
│                                                   │                         │
└───────────────────────────────────────────────────┴─────────────────────────┘
  • Row 1: Breadcrumb (with MG ID) + primary action button + actions dropdown (right-aligned)
  • Row 2: Entity name + status badge inline
  • Row 3: Subtitle (contextual info)
  • Status badge appears immediately after entity name (like Stripe), NOT on the right side competing with buttons

MG ID

MG ID is the staff shorthand used in Slack messages, verbal communication, etc. Displayed prominently in breadcrumb.

Entity MG ID Format Example Source
Reservation RSV{seq} RSV-22 Global sequence
Location {TypeCode}{seq} MG7 Location type code + local seq
Resource {locMgId}-{TypeCode}{seq} MG7-SMO248 Location MG ID + resource type code + local seq
Asset AST{seq} AST42 Global sequence
User (no MG ID)

MG ID service: apps/api/src/services/shared/MgIdService.ts Type codes: packages/shared-constants/src/mg-id.ts

Location type codes: MG (Metrognome), VNU (Venue), RTL (Retail), CMP (Competitor) Resource type codes: SMO (Studio Monthly), SHR (Studio Hourly), EQP (Equipment), STO (Storage), PRK (Parking), MBX (Mailbox), AMN (Amenity)

Header Examples

Lockout:

Reservations › RSV-22                                         [Edit Lockout] [...]

Studio 248  ● Active
TZTR TZTING · MG7 Cully

Location:

Locations › MG7                                              [Edit Location] [...]

Cully  ● Active
Portland, OR

Resource:

Locations › MG7 › Resources › MG7-SMO248                      [Edit Resource] [...]

Studio 248  ● Active
Monthly · MG7 Cully

User:

Users ›                                                           [Edit User] [...]

Aaron Hogan  ● Approved
aaron@example.com

Wireframes

Lockout Detail Page

┌─────────────────────────────────────────────────────────────────────────────┐
│  Reservations › RSV-22                                  [Edit Lockout] [...] │
│                                                                             │
│  Studio 248  ● Active                                                       │
│  TZTR TZTING · MG7 Cully                                                    │
│                                                                             │
│  Started          Next invoice                                              │
│  Jan 15           $421.95 on Feb 1                                          │
│                                                                             │
├───────────────────────────────────────────────────┬─────────────────────────┤
│                                                   │                         │
│  Payments                                         │  Details            ✎  │
│                                                   │                         │
│  Date        Amount     Status      Invoice       │  Customer               │
│  ──────────────────────────────────────────────   │  TZTR TZTING →          │
│  Jan 15      $421.95    ● Paid      inv_xxx  ...  │                         │
│                                                   │  Resource               │
│                                                   │  Studio 248 →           │
│  Transfers                                        │                         │
│                                                   │  Location               │
│  Date        Amount     Status      Account       │  MG7 Cully →            │
│  ──────────────────────────────────────────────   │                         │
│  Jan 16      $380.00    ● Complete  Cully    ...  │  ─────────────────────  │
│                                                   │                         │
│                                                   │  Subscription           │
│  Access Codes                              [+]    │                         │
│                                                   │  Stripe Sub             │
│  ┌──────────────────────────────────────────┐     │  sub_xxx →              │
│  │  123456    Dynamic PIN    Active    ...  │     │                         │
│  └──────────────────────────────────────────┘     │  Billing Anchor         │
│  ┌──────────────────────────────────────────┐     │  1st of month           │
│  │  789012    Static        Active    ...  │     │                         │
│  └──────────────────────────────────────────┘     │  Monthly Total          │
│                                                   │  $421.95                │
│                                                   │  $411 + $10.95 ins.     │
│                                                   │                         │
│                                                   │  Insurance              │
│                                                   │  $5,000 Coverage        │
│                                                   │                         │
│                                                   │  Promo Code             │
│                                                   │  —                      │
│                                                   │                         │
│                                                   │  ─────────────────────  │
│                                                   │                         │
│                                                   │  Notes                ✎ │
│                                                   │                         │
│                                                   │  Admin notes for this   │
│                                                   │  lockout                │
│                                                   │                         │
│                                                   │  ─────────────────────  │
│                                                   │                         │
│                                                   │  System                 │
│                                                   │                         │
│                                                   │  ID                     │
│                                                   │  LK-CU-248-T2T ⧉        │
│                                                   │                         │
│                                                   │  Created                │
│                                                   │  Jan 15, 2:34 PM        │
│                                                   │                         │
│                                                   │  Updated                │
│                                                   │  Jan 28, 9:12 AM        │
│                                                   │                         │
└───────────────────────────────────────────────────┴─────────────────────────┘

Location Detail Page

┌─────────────────────────────────────────────────────────────────────────────┐
│  Locations › MG7                                        [Edit Location] [...] │
│                                                                             │
│  Cully  ● Active                                                            │
│  Portland, OR                                                               │
│                                                                             │
├───────────────────────────────────────────────────┬─────────────────────────┤
│                                                   │                         │
│  Resources                                  [+]   │  Details            ✎  │
│                                                   │                         │
│  Name           Type       Status     Price       │  Type                   │
│  ──────────────────────────────────────────────   │  Metrognome             │
│  Studio 101     Monthly    Active     $285   ...  │                         │
│  Studio 102     Monthly    Active     $325   ...  │  Opened                 │
│  Studio 201     Hourly     Active     $28/hr ...  │  Mar 15, 2024           │
│  Drum Room      Hourly     Active     $35/hr ...  │                         │
│                                                   │  Slug                   │
│  View all 24 resources →                          │  cully                  │
│                                                   │                         │
│                                                   │  Description            │
│  Access Gates                               [+]   │  Premier rehearsal      │
│                                                   │  facility in NE         │
│  Device ID        Scope           Status          │  Portland...            │
│  ──────────────────────────────────────────────   │                         │
│  GATE-001         Location        Online     ...  │  ─────────────────────  │
│  GATE-002         Studio 248      Online     ...  │                         │
│                                                   │  Address            ✎  │
│                                                   │                         │
│  Images                                     [+]   │  4530 NE Cully Blvd     │
│                                                   │  Portland, OR 97218     │
│  ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐         │                         │
│  │     │ │     │ │     │ │     │ │     │         │  Timezone               │
│  └─────┘ └─────┘ └─────┘ └─────┘ └─────┘         │  America/Los_Angeles    │
│                                                   │                         │
│                                                   │  ─────────────────────  │
│  Directions                                 [+]   │                         │
│                                                   │  Contact            ✎  │
│  ┌──────────────────────────────────────────┐     │                         │
│  │  From I-84: Take exit 5...          ...  │     │  Phone                  │
│  └──────────────────────────────────────────┘     │  (503) 555-1234         │
│                                                   │                         │
│                                                   │  Email                  │
│                                                   │  cully@metrognome.com   │
│                                                   │                         │
│                                                   │  Manager                │
│                                                   │  Sarah Johnson →        │
│                                                   │                         │
│                                                   │  ─────────────────────  │
│                                                   │                         │
│                                                   │  Pricing            ✎  │
│                                                   │                         │
│                                                   │  Monthly Rate           │
│                                                   │  $10.00/sq ft           │
│                                                   │                         │
│                                                   │  Hourly Rate            │
│                                                   │  $2.50/sq ft            │
│                                                   │                         │
│                                                   │  Insurance              │
│                                                   │  Available, optional    │
│                                                   │                         │
│                                                   │  ─────────────────────  │
│                                                   │                         │
│                                                   │  Integrations       ✎  │
│                                                   │                         │
│                                                   │  Stripe Account         │
│                                                   │  acct_xxx →             │
│                                                   │                         │
│                                                   │  UniFi Group            │
│                                                   │  group_xxx              │
│                                                   │                         │
│                                                   │  ─────────────────────  │
│                                                   │                         │
│                                                   │  System                 │
│                                                   │  ID  loc_xxx ⧉           │
│                                                   │  Created  Jan 10, 2024  │
│                                                   │                         │
└───────────────────────────────────────────────────┴─────────────────────────┘

Resource Detail Page

┌─────────────────────────────────────────────────────────────────────────────┐
│  Locations › MG7 › Resources › MG7-SMO248               [Edit Resource] [...] │
│                                                                             │
│  Studio 248  ● Active                                                       │
│  Monthly · MG7 Cully                                                        │
│                                                                             │
├───────────────────────────────────────────────────┬─────────────────────────┤
│                                                   │                         │
│  Reservations                                     │  Details            ✎  │
│                                                   │                         │
│  Customer        Type      Start       Status     │  Type                   │
│  ──────────────────────────────────────────────   │  Monthly                │
│  TZTR TZTING     Lockout   Jan 15      Active     │                         │
│                                                   │  Status                 │
│                                                   │  ● Active               │
│  Asset Placements                           [+]   │                         │
│                                                   │  Availability           │
│  Asset           Category      Placed             │  Occupied               │
│  ──────────────────────────────────────────────   │                         │
│  Fender Twin     Amplifier     Jan 10        ...  │  Description            │
│  SM58 (x2)       Microphone    Jan 10        ...  │  Professional monthly   │
│                                                   │  rehearsal studio...    │
│                                                   │                         │
│  Resource Groups                                  │  ─────────────────────  │
│                                                   │                         │
│  ┌──────────────────────────────────────────┐     │  Location               │
│  │  Yellow Wing    Floor 2              ... │     │  MG7 Cully →            │
│  └──────────────────────────────────────────┘     │                         │
│                                                   │  ─────────────────────  │
│                                                   │                         │
│  Images                                     [+]   │  Physical           ✎  │
│                                                   │                         │
│  ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐                 │  Dimensions             │
│  │     │ │     │ │     │ │     │                 │  12' × 14' × 10'        │
│  └─────┘ └─────┘ └─────┘ └─────┘                 │                         │
│                                                   │  Max Occupancy          │
│                                                   │  4 people               │
│                                                   │                         │
│                                                   │  Floor / Wing           │
│                                                   │  2 / Yellow             │
│                                                   │                         │
│                                                   │  ─────────────────────  │
│                                                   │                         │
│                                                   │  Pricing            ✎  │
│                                                   │                         │
│                                                   │  Card Price             │
│                                                   │  $411.00/mo             │
│                                                   │                         │
│                                                   │  ACH Price              │
│                                                   │  $395.00/mo             │
│                                                   │                         │
│                                                   │  Rate per Sq Ft         │
│                                                   │  $2.45                  │
│                                                   │                         │
│                                                   │  ─────────────────────  │
│                                                   │                         │
│                                                   │  Notes                ✎ │
│                                                   │  Good natural light,    │
│                                                   │  corner unit            │
│                                                   │                         │
│                                                   │  ─────────────────────  │
│                                                   │                         │
│                                                   │  System                 │
│                                                   │  ID  res_xxx ⧉           │
│                                                   │  MG ID  CU-248          │
│                                                   │                         │
└───────────────────────────────────────────────────┴─────────────────────────┘

Edit Sheet (Vaul drawer from right)

                                                ┌─────────────────────────────┐
                                                │                             │
                                                │  Edit Lockout           ✕   │
                                                │                             │
                                                │  Studio                     │
                                                │  ───────────────────────    │
                                                │                             │
                                                │  Location                   │
                                                │  ┌─────────────────────┐    │
                                                │  │ MG7 Cully         ▾ │    │
                                                │  └─────────────────────┘    │
                                                │                             │
                                                │  Resource                   │
                                                │  ┌─────────────────────┐    │
                                                │  │ Studio 248        ▾ │    │
                                                │  └─────────────────────┘    │
                                                │                             │
                                                │  Pricing                    │
                                                │  ───────────────────────    │
                                                │                             │
                                                │  ┌──────────┐ ┌──────────┐  │
                                                │  │ Card $   │ │ ACH $    │  │
                                                │  │ 411.00   │ │          │  │
                                                │  └──────────┘ └──────────┘  │
                                                │  Leave blank for default    │
                                                │                             │
                                                │  Insurance                  │
                                                │  ───────────────────────    │
                                                │                             │
                                                │  ┌─────────────────────┐    │
                                                │  │ $5,000 Coverage   ▾ │    │
                                                │  └─────────────────────┘    │
                                                │                             │
                                                │  When to apply              │
                                                │  ───────────────────────    │
                                                │                             │
                                                │  ● Immediately              │
                                                │  ○ Next billing cycle       │
                                                │                             │
                                                │  ┌─────────────────────────┐│
                                                │  │ No changes to preview   ││
                                                │  └─────────────────────────┘│
                                                │                             │
                                                │  ┌────────┐  ┌────────────┐ │
                                                │  │ Cancel │  │   Update   │ │
                                                │  └────────┘  └────────────┘ │
                                                │                             │
                                                └─────────────────────────────┘

Section Edit Sheet (small/focused)

                                                ┌─────────────────────────────┐
                                                │                             │
                                                │  Edit Notes             ✕   │
                                                │                             │
                                                │  ┌─────────────────────────┐│
                                                │  │ Admin notes for this    ││
                                                │  │ lockout                 ││
                                                │  │                         ││
                                                │  │                         ││
                                                │  └─────────────────────────┘│
                                                │  Internal notes, staff only │
                                                │                             │
                                                │  ┌────────┐  ┌────────────┐ │
                                                │  │ Cancel │  │    Save    │ │
                                                │  └────────┘  └────────────┘ │
                                                │                             │
                                                └─────────────────────────────┘

Actions Menu Examples

Lockout:                          User:                           Location:
┌─────────────────────────┐       ┌─────────────────────────┐     ┌─────────────────────────┐
│  Pause billing          │       │  Send password reset    │     │  Duplicate location     │
│  Send payment link      │       │  Impersonate user       │     │  Export resources       │
│  View in Stripe →       │       │  View in Stripe →       │     │  View in Stripe →       │
│  ─────────────────────  │       │  ─────────────────────  │     │  ─────────────────────  │
│  Cancel subscription    │       │  Delete user            │     │  Deactivate location    │
└─────────────────────────┘       └─────────────────────────┘     └─────────────────────────┘

Create Flow

List pages have a [+ Add X] button that opens a create sheet:

┌─────────────────────────────────────────────────────────────────────────────┐
│  Resources                                               [+ Add Resource]   │
├─────────────────────────────────────────────────────────────────────────────┤
│  Name           Location     Type       Status     Price                    │
│  ─────────────────────────────────────────────────────────────────────────  │
│  Studio 101     MG7 Cully    Monthly    Active     $285                     │
│  ...                                                                        │
└─────────────────────────────────────────────────────────────────────────────┘

Create sheet uses the same EditSheet component. On save: POST to API → close sheet → redirect to new entity detail page.


Content Architecture by Entity

Lockout (Reservation - STUDIO_MONTHLY)

Main Column: | Section | Content | |---------|---------| | Payments | Table: date, amount, status, invoice link, row actions | | Transfers | Table: date, amount, status, account | | Access Codes | Table: code, type (dynamic/static), status. Can have MULTIPLE codes (front gate, wing, studio door) |

Sidebar: | Section | Fields | Editable? | |---------|--------|-----------| | Details | Customer (link), Resource (link), Location (link) | Via primary edit | | Subscription | Stripe Sub (link), Billing Anchor, Monthly Total (with insurance breakdown), Insurance, Promo Code | Via primary edit | | Notes | Admin notes | ✎ section edit | | System | ID, MG ID, Created, Updated | Read-only |

Primary Edit Sheet fields: Location, Resource, Card Price, ACH Price, Insurance, Timing (immediate vs next cycle), with subscription preview/proration

Actions Menu: Pause billing, Send payment link, View in Stripe, Cancel subscription

Important domain notes:

  • Insurance is part of the subscription/billing, NOT the studio itself
  • From lockout detail, you edit lockout properties (assignment, pricing). To edit the studio itself (name, dimensions), go to the resource detail page
  • Access codes are per-reservation, not per-resource. A lockout can include codes for front gate, wing door, and studio door

User

Main Column: | Section | Content | |---------|---------| | Reservations | Table: name, location, type, status | | Transactions | Table: date, description, amount | | Credit Balances | Table: location, balance | | Access Codes | Table: code, location, resource, status | | Waitlist | Table: entries or empty state |

Sidebar: | Section | Fields | Editable? | |---------|--------|-----------| | Profile | Name, Email, Phone, Bio | ✎ section edit | | Status | Approved, Organization | ✎ section edit | | Billing | Stripe Customer (link), Stripe Balance | ✎ section edit | | Notes | Admin notes | ✎ section edit | | System | ID, Auth ID, Created, Last Login | Read-only |

Primary Edit Sheet: Name, Email (read-only), Phone, Bio, Approved status

Actions Menu: Send password reset, Impersonate, View in Stripe, Delete user


Location

Main Column: | Section | Content | |---------|---------| | Resources | Table: name, type, status, price, row actions | | Access Gates | Table: device ID, scope, status | | Images | Grid with add/remove | | Directions | List with add/remove |

Sidebar: | Section | Fields | Editable? | |---------|--------|-----------| | Details | Type (immutable), Opened, Slug, Description | ✎ section edit | | Address | Street, City, State, ZIP, Timezone, Coordinates, Parking | ✎ section edit | | Contact | Phone, Email, Website, Manager (link) | ✎ section edit | | Pricing | Monthly Rate, Hourly Rate, Peak Multiplier, Insurance settings | ✎ section edit | | Integrations | Stripe Account (link), UniFi Group | ✎ section edit | | System | ID, MG ID, Created, Updated | Read-only |

Primary Edit Sheet: Name, Status, Description, Notes, Slug, Opened date

Actions Menu: Duplicate location, Export resources, View in Stripe, Deactivate


Resource

Main Column: | Section | Content | |---------|---------| | Reservations | Table: customer, type, start, status | | Asset Placements | Table: asset, category, placed date | | Resource Groups | List of group memberships | | Images | Grid with add/remove |

Sidebar: | Section | Fields | Editable? | |---------|--------|-----------| | Details | Type (immutable), Status, Availability, Description, Featured | Via primary edit | | Location | Location (link), Acuity Calendar | Via primary edit | | Physical | Dimensions, Area, Max Occupancy, Floor, Wing | ✎ section edit | | Pricing | Card Price, ACH Price, Rate per Sq Ft, Peak settings | ✎ section edit | | Notes | Admin notes | ✎ section edit | | System | ID, MG ID, Created, Updated | Read-only |

Primary Edit Sheet: Name, Status, Description, Availability, Featured, Acuity Calendar ID

Actions Menu: Duplicate resource, View reservations, Delete resource


Asset

Main Column: | Section | Content | |---------|---------| | Placement History | Table: location, scope, placed date, removed date | | Component Installations | Table: component, installed date (if applicable) |

Sidebar: | Section | Fields | Editable? | |---------|--------|-----------| | Details | Category (immutable), Subcategory, Status, Condition, Consumable, Description | Via primary edit | | Equipment | Manufacturer, Model, Serial Number | ✎ section edit | | Purchase | Date, Price, Vendor, Order Number | ✎ section edit | | Warranty | Expiration, Notes | ✎ section edit | | System | ID, MG ID, Created, Updated | Read-only |

Primary Edit Sheet: Name, Status, Condition, Description, Consumable flag

Actions Menu: Duplicate asset, Delete asset


Organization

Main Column: | Section | Content | |---------|---------| | Members | Table: users with this email domain | | Credit Balances | Table: location, balance |

Sidebar: | Section | Fields | Editable? | |---------|--------|-----------| | Details | Name, Email Domain | Via primary edit | | Owner | Owner (link) | ✎ section edit | | System | ID, Created, Updated | Read-only |

Primary Edit Sheet: Name, Email Domain

Actions Menu: Delete organization


Component Architecture

New Components

apps/web/src/components/
├── molecules/
│   ├── detail/
│   │   ├── DetailLayout.tsx           # Two-column responsive layout
│   │   ├── DetailHeader.tsx           # Breadcrumb, title, status, CTAs
│   │   ├── DetailSection.tsx          # Sidebar section card with optional ✎
│   │   ├── DetailTable.tsx            # Main column table with row actions
│   │   ├── DisplayField.tsx           # Label + value for sidebar
│   │   ├── DisplayGrid.tsx            # Grid of DisplayFields
│   │   └── index.ts                   # Barrel export
│   └── sheets/
│       └── EditSheet.tsx              # Vaul drawer wrapper (create + edit)
├── organisms/
│   ├── detail/
│   │   ├── LockoutDetail.tsx          # Lockout detail page content
│   │   ├── UserDetail.tsx
│   │   ├── LocationDetail.tsx
│   │   ├── ResourceDetail.tsx
│   │   ├── AssetDetail.tsx
│   │   └── OrganizationDetail.tsx
│   └── sheets/
│       ├── resource/
│       │   ├── ResourceSheet.tsx       # Create + primary edit
│       │   ├── EditResourcePhysicalSheet.tsx
│       │   ├── EditResourcePricingSheet.tsx
│       │   └── EditResourceNotesSheet.tsx
│       ├── lockout/
│       │   ├── LockoutSheet.tsx        # Create + primary edit (subscription)
│       │   └── EditLockoutNotesSheet.tsx
│       ├── location/
│       │   ├── LocationSheet.tsx       # Create + primary edit
│       │   ├── EditLocationAddressSheet.tsx
│       │   ├── EditLocationContactSheet.tsx
│       │   ├── EditLocationPricingSheet.tsx
│       │   └── EditLocationIntegrationsSheet.tsx
│       ├── user/
│       │   ├── UserSheet.tsx           # Create + primary edit
│       │   ├── EditUserProfileSheet.tsx
│       │   ├── EditUserStatusSheet.tsx
│       │   ├── EditUserBillingSheet.tsx
│       │   └── EditUserNotesSheet.tsx
│       ├── asset/
│       │   ├── AssetSheet.tsx
│       │   ├── EditAssetEquipmentSheet.tsx
│       │   ├── EditAssetPurchaseSheet.tsx
│       │   └── EditAssetWarrantySheet.tsx
│       └── organization/
│           ├── OrganizationSheet.tsx
│           └── EditOrganizationOwnerSheet.tsx

Component Specifications

DetailLayout

  • Props: children (main column), sidebar (sidebar content)
  • Two-column grid on desktop (main ~65%, sidebar ~35%)
  • Single column on mobile (main content first, then sidebar below)
  • Handles responsive breakpoint

DetailHeader

  • Props: breadcrumbs, title, subtitle, status, primaryAction, actionsMenu
  • Row 1: Breadcrumb (includes MG ID) + primary action button + actions dropdown (right-aligned)
  • Row 2: Title + status badge inline (e.g., "Studio 248 ● Active")
  • Row 3: Subtitle (contextual info - customer, location, etc.)

DetailSection

  • Props: title, onEdit?, children
  • Card with title and optional edit pencil button
  • Used in sidebar for property groups

DetailTable

  • Props: title, columns, data, onAdd?, emptyMessage, viewAllHref?
  • Consistent table styling
  • Row actions via ... menu
  • Optional [+] add button in header
  • "View all →" link if data is paginated/truncated

DisplayField

  • Props: label, value, href?, copyable?, description?
  • Clean label + value display
  • Optional link styling (for entity references)
  • Optional copy button (for IDs, subscription IDs)

DisplayGrid

  • Props: children (DisplayField components)
  • Arranges DisplayFields in consistent spacing

EditSheet

  • Props: title, isOpen, onClose, onSave, isLoading, children
  • Vaul drawer from right side
  • Header with title + close button
  • Scrollable content area for form fields
  • Sticky footer with Cancel + Save/Update/Create buttons
  • Used for both create and edit flows (different title and button labels)

Implementation Phases

Phase 1: Foundation Components

Scope: Build reusable detail components

Tasks:

  1. Create DetailLayout component with responsive two-column grid
  2. Create DetailHeader component with breadcrumb, title, status, actions
  3. Create DetailSection component for sidebar cards
  4. Create DetailTable component for main column tables
  5. Create DisplayField and DisplayGrid components
  6. Create EditSheet wrapper using Vaul (already installed: vaul: ^1.1.2)

Files to create:

  • apps/web/src/components/molecules/detail/DetailLayout.tsx
  • apps/web/src/components/molecules/detail/DetailHeader.tsx
  • apps/web/src/components/molecules/detail/DetailSection.tsx
  • apps/web/src/components/molecules/detail/DetailTable.tsx
  • apps/web/src/components/molecules/detail/DisplayField.tsx
  • apps/web/src/components/molecules/detail/DisplayGrid.tsx
  • apps/web/src/components/molecules/detail/index.ts
  • apps/web/src/components/molecules/sheets/EditSheet.tsx

Phase 2: Prototype on Resource

Scope: Build complete Resource detail page + create flow as reference implementation

Why Resource: Has good variety of content types (tables, images, sidebar sections with edit buttons) without the subscription/billing complexity of Lockout

Tasks:

  1. Create ResourceDetail.tsx display component
  2. Create ResourceSheet.tsx for primary edit and create (shared component with mode prop)
  3. Create EditResourcePhysicalSheet.tsx for physical properties section
  4. Create EditResourcePricingSheet.tsx for pricing section
  5. Create EditResourceNotesSheet.tsx for notes section
  6. Wire up data fetching and mutations
  7. Update detail page [id]/page.tsx
  8. Update list page to use create sheet instead of /new route
  9. Test responsive behavior (two-column → single column)

Files to create/modify:

  • apps/web/src/components/organisms/detail/ResourceDetail.tsx (create)
  • apps/web/src/components/organisms/sheets/resource/ResourceSheet.tsx (create)
  • apps/web/src/components/organisms/sheets/resource/EditResourcePhysicalSheet.tsx (create)
  • apps/web/src/components/organisms/sheets/resource/EditResourcePricingSheet.tsx (create)
  • apps/web/src/components/organisms/sheets/resource/EditResourceNotesSheet.tsx (create)
  • apps/web/src/app/(app)/staff/resources/[id]/page.tsx (modify)
  • apps/web/src/app/(app)/staff/resources/[id]/EditReservationPage.tsx (replace)
  • apps/web/src/app/(app)/staff/resources/page.tsx (modify list page for create sheet)
  • apps/web/src/app/(app)/staff/resources/new/ (remove after migration)

Phase 3: Location

Scope: Apply pattern to Location

Tasks:

  1. Create LocationDetail.tsx
  2. Create LocationSheet.tsx (create + primary edit)
  3. Create section edit sheets: address, contact, pricing, integrations
  4. Update list page for create sheet, remove /new route
  5. Wire up data and mutations
  6. Test

Phase 4: User

Scope: Apply pattern to User (more tables in main column)

Tasks:

  1. Create UserDetail.tsx
  2. Create UserSheet.tsx (create + primary edit)
  3. Create section edit sheets: profile, status, billing, notes
  4. Update list page for create sheet, remove /new route
  5. Wire up data and mutations
  6. Test

Phase 5: Lockout

Scope: Apply pattern to Lockout (most complex due to subscription logic)

Tasks:

  1. Create LockoutDetail.tsx
  2. Create LockoutSheet.tsx (create + primary edit with subscription logic)
  3. Create section edit sheets: notes
  4. Handle subscription preview/proration logic in primary sheet
  5. Update list page for create sheet, remove /new route
  6. Wire up existing subscription metadata endpoints
  7. Test

Phase 6: Remaining Entities

Scope: Asset and Organization

Tasks:

  1. Create AssetDetail.tsx, AssetSheet.tsx, and section sheets
  2. Create OrganizationDetail.tsx, OrganizationSheet.tsx, and section sheets
  3. Update list pages for create sheets, remove /new routes
  4. Test

Phase 7: Cleanup

Scope: Remove old code

Tasks:

  1. Remove old form components (LockoutForm.tsx, LocationForm.tsx, ResourceForm.tsx, UserForm.tsx, AssetForm.tsx, OrganizationForm.tsx)
  2. Remove old /new page routes
  3. Remove unused StaffFormLayout.tsx, FormSection.tsx if no longer needed
  4. Update any shared navigation/links
  5. Final testing across all entities
  6. Mobile responsive testing

Migration Strategy

  • Replace in place - Update existing routes directly (no parallel routes)
  • Create flows also use sheets - [+ Add X] on list pages opens create sheet, redirects to detail on save
  • Reuse form logic - Sheets reuse existing Zod schemas and field components (selectors, inputs, etc.)
  • Incremental rollout - Deploy one entity at a time, each phase is independently shippable

Verification Plan

Per-Entity Testing

  1. Navigate to entity list → click entity → verify detail page renders correctly
  2. Verify two-column layout on desktop, single column on mobile
  3. Verify MG ID appears in breadcrumb
  4. Click primary edit button → verify sheet opens with correct data pre-filled
  5. Make changes → save → verify data updates on page
  6. Click section edit buttons (✎) → verify focused sheet opens
  7. Test actions menu items
  8. Verify all links work (breadcrumb, related entities in sidebar, table row links)
  9. Test empty states (no reservations, no placements, etc.)

Create Flow Testing

  1. Navigate to entity list page
  2. Click [+ Add X] button → verify create sheet opens
  3. Fill required fields → save → verify redirects to new entity detail page
  4. Verify new entity appears in list

Cross-Entity Testing

  1. Navigate between entities via links (user → reservation → resource → location)
  2. Verify consistent styling and behavior across all entity types
  3. Test on mobile viewport

Regression Testing

  1. Run existing test suites

Decisions Log

Decision Choice Rationale
Vaul for sheets ✅ Already installed (vaul: ^1.1.2)
Create flow Sheet-based (same as edit) Consistency across all flows
URL structure Replace in place Simpler, no parallel route cleanup
Column layout Two-column (main + sidebar) Enough activity data to justify (payments, reservations, placements, access codes)
Status badge position Inline with entity name Don't compete with header buttons
Prototype entity Resource Good variety without subscription complexity
Insurance grouping Part of subscription, not studio Insurance is a billing concern, not a physical property

Existing Files Reference

Form Files (to be removed in Phase 7)

  • apps/web/src/components/organisms/forms/LockoutForm.tsx
  • apps/web/src/components/organisms/forms/LocationForm.tsx
  • apps/web/src/components/organisms/forms/ResourceForm.tsx
  • apps/web/src/components/organisms/forms/UserForm.tsx
  • apps/web/src/components/organisms/forms/AssetForm.tsx
  • apps/web/src/components/organisms/forms/OrganizationForm.tsx

Layout Files (to be removed/replaced in Phase 7)

  • apps/web/src/components/molecules/forms/StaffFormLayout.tsx
  • apps/web/src/components/molecules/forms/FormSection.tsx
  • apps/web/src/components/atoms/forms/LabeledValue.tsx

Reusable Field Components (keep and use in sheets)

  • apps/web/src/components/molecules/forms/LocationSelector.tsx
  • apps/web/src/components/molecules/forms/ResourceSelector.tsx
  • apps/web/src/components/molecules/forms/UserSelector.tsx
  • apps/web/src/components/molecules/forms/InsuranceSelector.tsx
  • apps/web/src/components/molecules/forms/CouponSelector.tsx
  • apps/web/src/components/molecules/forms/AccessCodeSelector.tsx
  • apps/web/src/components/molecules/forms/RecipientInput.tsx
  • apps/web/src/components/molecules/forms/AddressAutocomplete.tsx
  • apps/web/src/components/molecules/forms/AssetSelector.tsx
  • apps/web/src/components/molecules/forms/FormFieldGroup.tsx
  • apps/web/src/components/molecules/forms/PeakHours.tsx

Data Hooks (to wire up main column tables)

  • apps/web/src/hooks/api/useReservations.ts
  • apps/web/src/hooks/api/useTransactions.ts
  • apps/web/src/hooks/api/useAccessCodes.ts
  • apps/web/src/hooks/api/useAssetPlacements.ts
  • apps/web/src/hooks/api/useResources.ts
  • apps/web/src/hooks/api/useLocations.ts

MG ID System

  • apps/api/src/services/shared/MgIdService.ts - Allocates sequences, builds MG IDs
  • packages/shared-constants/src/mg-id.ts - Type codes (MG, SMO, SHR, etc.)
  • GET /reservations/[id] - Reservation + location + resource + user + payments
  • GET /reservations/[id]/subscription-metadata - Subscription health, transfer info
  • GET /reservations/[id]/access-codes - Dynamic/static access codes
  • POST /lockouts/[id]/preview-transfer - Preview transfer/proration calculation
  • GET /resources/[id] - Resource details
  • GET /resources?locationId=X - Resources at location
  • GET /access-gates?locationId=X - Access gates at location
  • GET /asset-placements?resourceId=X - Asset placements
  • GET /users/[id] - User details
  • GET /users/[id]/stripe-balance - Stripe customer balance