424 lines
22 KiB
Markdown
424 lines
22 KiB
Markdown
# Spool Detail View — Screen Specification
|
||
|
||
> **Screen ID:** FIL-002
|
||
> **Source of Truth:** [Material Design 3](https://m3.material.io/)
|
||
> **Tone:** Modern Industrial/Maker
|
||
> **Theme:** Dark Mode, High-Contrast
|
||
> **Last Updated:** 2026-04-20
|
||
|
||
---
|
||
|
||
## 1. Objective
|
||
|
||
Present comprehensive, actionable information about a single filament spool. Users (shop operators) must be able to:
|
||
|
||
- View all spool metadata (material, brand, color, weight, location, dates).
|
||
- See real-time remaining weight with visual progress indicator.
|
||
- Manage QR code (view, reprint label).
|
||
- View consumption history / usage timeline.
|
||
- Perform quick actions: edit details, move location, mark depleted, initiate print.
|
||
- Navigate back to inventory or forward to related entities (printer, location).
|
||
|
||
This is the **drill-down screen** from the Filament Inventory List.
|
||
|
||
---
|
||
|
||
## 2. Screen Inventory
|
||
|
||
| Element | MD3 Component | Notes |
|
||
|---------|--------------|-------|
|
||
| Top App Bar | `md-top-app-bar` (small) | Back nav + title + actions |
|
||
| Hero Section | Custom card | Color swatch + material name + status badge |
|
||
| Progress Ring | `md-circular-progress` (determinate) | Circular remaining-weight indicator |
|
||
| Metrics Grid | CSS Grid in `md-card` | Key metrics in 2-col grid |
|
||
| QR Code Card | `md-card` (elevated) | QR display + reprint button |
|
||
| Location Section | `md-card` (outlined) | Current location + move action |
|
||
| Usage Timeline | `md-list` (2-line) | Recent consumption events |
|
||
| Action Row | `md-button` row | Primary + secondary actions |
|
||
| Snackbar | `md-snackbar` | Confirmation for destructive actions |
|
||
| Dialog | `md-dialog` | Move location, confirm depletion |
|
||
|
||
---
|
||
|
||
## 3. Layout Specification
|
||
|
||
### Title
|
||
**Spool detail name** — displayed in the Top App Bar headline slot (material short name, e.g., "PLA Basic — Matte Black").
|
||
|
||
### Sections
|
||
|
||
#### A. Top App Bar (64dp)
|
||
- **Leading:** Back arrow → returns to Inventory List
|
||
- **Title:** Material name (scrolls into collapsed bar on scroll)
|
||
- **Trailing actions:** Edit icon (pencil), More (overflow: Delete spool, Transfer data)
|
||
|
||
#### B. Hero Section (200dp mobile / 180dp kiosk)
|
||
A prominent visual header that establishes identity at a glance:
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────┐
|
||
│ │
|
||
│ ┌──────┐ │
|
||
│ │ COLOR│ PLA Basic — Matte Black │
|
||
│ │SWATCH│ Bambu Lab │
|
||
│ │ 80dp │ │
|
||
│ └──────┘ [Available] │
|
||
│ │
|
||
│ ◉ 842g / 1000g │
|
||
│ 67% remaining │
|
||
│ │
|
||
└──────────────────────────────────────────────────┘
|
||
```
|
||
|
||
- **Left:** Large circular color swatch (80dp) with `outlineVariant` border
|
||
- **Right of swatch:**
|
||
- Line 1: Full material name (`headlineMedium`) — MaterialBase + Finish + Modifier
|
||
- Line 2: Brand name (`bodyLarge`, `onSurfaceVariant`)
|
||
- **Below swatch row:** Status badge (tonal chip, same as inventory)
|
||
- **Bottom:** Large circular progress indicator (96dp ring)
|
||
- Track: `surfaceContainerHighest`
|
||
- Indicator: Dynamic color (≥25% primary, 10-24% warning, <10% error)
|
||
- Center text: Remaining weight + percentage (`headlineSmall`)
|
||
|
||
#### C. Metrics Grid (2-column)
|
||
|
||
```
|
||
┌────────────────────┬────────────────────┐
|
||
│ Total Weight │ Remaining │
|
||
│ 1,000g │ 842g (67%) │
|
||
├────────────────────┼────────────────────┤
|
||
│ Diameter │ Density │
|
||
│ 1.75mm │ 1.24 g/cm³ │
|
||
├────────────────────┼────────────────────┤
|
||
│ Date Added │ Last Used │
|
||
│ Mar 12, 2026 │ Apr 18, 2026 │
|
||
└────────────────────┴────────────────────┘
|
||
```
|
||
|
||
- Each cell: Label (`labelMedium`, `onSurfaceVariant`) + Value (`titleMedium`, `onSurface`)
|
||
- Grid gap: 1dp `outlineVariant` lines between cells
|
||
- Container: `surfaceContainer` background, `rounded-xl` (16dp radius)
|
||
- Cell padding: 16dp
|
||
|
||
#### D. Location Card (Outlined, 72dp)
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────┐
|
||
│ 📍 AMS Unit 2, Slot A3 [Move]│
|
||
│ Bambu Lab P1S — Left spool holder │
|
||
└──────────────────────────────────────────────────┘
|
||
```
|
||
|
||
- **Leading:** Location pin icon
|
||
- **Line 1:** Location name (`titleSmall`, `onSurface`)
|
||
- **Line 2:** Printer/host description (`bodySmall`, `onSurfaceVariant`)
|
||
- **Trailing:** "Move" text button (`primary`) → opens Move Location dialog
|
||
|
||
#### E. QR Code Card (Elevated, 200dp × 200dp QR)
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────┐
|
||
│ ┌──────────────┐ │
|
||
│ │ │ │
|
||
│ │ QR CODE │ │
|
||
│ │ (160dp) │ │
|
||
│ │ │ │
|
||
│ └──────────────┘ │
|
||
│ EXT-2026-PLA-0042 │
|
||
│ [Reprint] │
|
||
└──────────────────────────────────────────────────┘
|
||
```
|
||
|
||
- QR code: 160dp × 160dp, white on dark surface
|
||
- Below QR: Internal tracking ID in monospace (`labelMedium`, `onSurfaceVariant`)
|
||
- Trailing: "Reprint" text button → sends to Bluetooth thermal printer
|
||
- Card: `surfaceContainerHigh` background, elevation 1
|
||
|
||
#### F. Usage Timeline (Expandable section)
|
||
|
||
```
|
||
│ Recent Usage │
|
||
│──────────────────────────────────────────────────│
|
||
│ 📦 Print #1847 — Benchy v3 -32g Apr 18│
|
||
│ 📦 Print #1842 — Housing Cap -18g Apr 17│
|
||
│ 📦 Print #1839 — Gear Test -8g Apr 16│
|
||
│ 📦 Added to inventory +1000g Mar 12│
|
||
│ │
|
||
│ [View Full History →] │
|
||
└───────────────────────────────────────────────────┘
|
||
```
|
||
|
||
- Each entry: 2-line list item
|
||
- Line 1: Print name or event (`bodyMedium`, `onSurface`)
|
||
- Line 2: Weight change + date (`bodySmall`, `onSurfaceVariant`)
|
||
- Negative weight: `error` color
|
||
- Positive weight: custom `success` color
|
||
- Trailing: "View Full History" link → separate screen (future)
|
||
|
||
#### G. Action Row (Sticky bottom, 64dp)
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────┐
|
||
│ [Mark Depleted] [Move Location] [Print] │
|
||
└──────────────────────────────────────────────────┘
|
||
```
|
||
|
||
- **Mark Depleted:** Outlined button, `error` color → confirmation dialog
|
||
- **Move Location:** Tonal button, `secondary` → Move Location dialog
|
||
- **Print:** Filled button, `primary` → Navigate to start print job (pre-select this spool)
|
||
|
||
On kiosk, these are larger touch targets (56dp height buttons).
|
||
|
||
### Primary CTA
|
||
**Print** (filled button) — the most likely next action after viewing spool details.
|
||
|
||
### Secondary Actions
|
||
- Edit (Top App Bar icon) → Edit spool details form
|
||
- Reprint label → Send QR to thermal printer
|
||
- Move Location → Dialog with location picker
|
||
- Mark Depleted → Confirmation dialog → status update
|
||
- Delete spool → Overflow menu → confirmation dialog
|
||
|
||
### Key Components
|
||
- Large circular color swatch
|
||
- Determinate circular progress indicator
|
||
- 2-column metrics grid
|
||
- QR code display card
|
||
- Location card with move action
|
||
- Usage timeline list
|
||
- Sticky bottom action row
|
||
|
||
### States
|
||
| State | Visual |
|
||
|-------|--------|
|
||
| **Loading** | `md-circular-progress` indeterminate centered, skeleton sections |
|
||
| **Available (normal)** | Primary color progress ring, "Available" badge |
|
||
| **In Use** | Primary color progress ring, "In Use" badge, pulsing dot |
|
||
| **Low Stock** | Warning (yellow) progress ring, "Low Stock" badge |
|
||
| **Critical** | Error (red) progress ring, "Critical" badge, pulsing dot |
|
||
| **Depleted** | Error (red) progress ring at 0%, "Depleted" badge, strikethrough weight, "Mark Depleted" button becomes "Reactivate" |
|
||
| **No Location** | Location card shows "Unassigned" + "Assign" button |
|
||
| **QR Missing** | QR card shows "No QR generated" + "Generate" button |
|
||
| **Move Dialog** | Bottom sheet (mobile) / Center dialog (kiosk) with location tree/grid selector |
|
||
|
||
---
|
||
|
||
## 4. UX Rationale
|
||
|
||
1. **Hero section for instant recognition.** When an operator scans a spool or taps into it, they need immediate visual confirmation: "Is this the spool I think it is?" The large color swatch + material name + brand answers this in <1 second.
|
||
|
||
2. **Circular progress over linear.** For a single spool, a circular progress ring is more impactful and glanceable than a linear bar. It works as a "fuel gauge" metaphor that operators intuitively understand.
|
||
|
||
3. **Metrics grid, not a list.** A 2-column grid presents data-dense information efficiently. Each metric is a quick scan without vertical scrolling. This is the "dashboard gauge" pattern adapted for a single entity.
|
||
|
||
4. **QR card always visible.** The QR code is the physical-digital bridge. Operators need to see it to verify labels match, and the reprint action is frequent (labels get damaged/lost on spools).
|
||
|
||
5. **Timeline for consumption context.** "How fast am I going through this spool?" The recent usage list answers this without requiring a separate analytics screen. It's contextual, not analytical.
|
||
|
||
6. **Sticky action row.** The three most common actions (deplete, move, print) should never be hidden by scroll. Pinning them ensures they're always one tap away.
|
||
|
||
7. **"Mark Depleted" is destructive but necessary.** It gets an outlined (not filled) style and requires a confirmation dialog to prevent accidental taps — but it's prominent because operators genuinely need this action often.
|
||
|
||
---
|
||
|
||
## 5. Visual Direction
|
||
|
||
### Typography (MD3 Type Scale)
|
||
|
||
| Role | Token | Size | Weight | Line Height |
|
||
|------|-------|------|--------|-------------|
|
||
| App Bar Title | `titleLarge` | 22sp | 400 | 28sp |
|
||
| Hero Material Name | `headlineMedium` | 28sp | 400 | 36sp |
|
||
| Hero Brand | `bodyLarge` | 16sp | 400 | 24sp |
|
||
| Progress Center Value | `headlineSmall` | 24sp | 400 | 32sp |
|
||
| Progress Center Sub | `labelMedium` | 12sp | 500 | 16sp |
|
||
| Metrics Label | `labelMedium` | 12sp | 500 | 16sp |
|
||
| Metrics Value | `titleMedium` | 16sp | 500 | 24sp |
|
||
| Card Title | `titleSmall` | 14sp | 500 | 20sp |
|
||
| Card Body | `bodyMedium` | 14sp | 400 | 20sp |
|
||
| Timeline Entry | `bodyMedium` | 14sp | 400 | 20sp |
|
||
| Timeline Detail | `bodySmall` | 12sp | 400 | 16sp |
|
||
| Action Button | `labelLarge` | 14sp | 500 | 20sp |
|
||
| Tracking ID | `labelMedium` (monospace) | 12sp | 500 | 16sp |
|
||
|
||
### Spacing (MD3 8dp grid)
|
||
|
||
| Element | Spacing |
|
||
|---------|---------|
|
||
| Hero section padding | 24dp horizontal, 20dp vertical |
|
||
| Swatch to text gap | 16dp |
|
||
| Hero to metrics gap | 16dp |
|
||
| Metrics grid cell padding | 16dp |
|
||
| Metrics grid gap (divider) | 1dp |
|
||
| Section gap (between cards) | 12dp |
|
||
| Card internal padding | 16dp |
|
||
| QR code padding | 24dp (centered) |
|
||
| Timeline item padding | 16dp horizontal, 12dp vertical |
|
||
| Action row padding | 16dp horizontal, 12dp vertical |
|
||
| Action button gap | 12dp |
|
||
|
||
### Color (MD3 Dark Theme — "Industrial Maker")
|
||
|
||
Same base palette as FIL-001. Screen-specific additions:
|
||
|
||
| Role | Token | Value (Dark) | Usage |
|
||
|------|-------|-------------|-------|
|
||
| Hero Background | `surfaceContainerLow` | `#1D1B20` | Hero section fill |
|
||
| Metrics Background | `surfaceContainer` | `#211F26` | Grid card |
|
||
| QR Card Background | `surfaceContainerHigh` | `#2B2930` | Elevated card |
|
||
| Location Card Background | `surfaceContainer` | `#211F26` | Outlined card |
|
||
| Progress Track | `surfaceContainerHighest` | `#36343B` | Ring background track |
|
||
| Depleted Strikethrough | `error` | `#F2B8B5` | Weight text decoration |
|
||
|
||
### Circular Progress Colors (Dynamic)
|
||
|
||
| Threshold | Color Token | Visual |
|
||
|-----------|------------|--------|
|
||
| ≥ 25% | `primary` | `#A8CEDA` (teal-blue) |
|
||
| 10–24% | Custom `warning` | `#FFD580` (amber) |
|
||
| < 10% | `error` | `#F2B8B5` (red) |
|
||
| 0% (Depleted) | `error` | `#F2B8B5` + pulsing animation |
|
||
|
||
---
|
||
|
||
## 6. Responsiveness
|
||
|
||
### Kiosk (800×480)
|
||
|
||
```
|
||
┌──────┬──────────────────────────────────────────────┐
|
||
│ NAV │ ← PLA Basic — Matte Black [✏] [⋮] │
|
||
│ RAIL │──────────────────────────────────────────────│
|
||
│ │ ┌──────┐ │
|
||
│ │ │SWATCH│ PLA Basic — Matte Black [Avail] │
|
||
│ │ │ 80dp │ Bambu Lab │
|
||
│ │ └──────┘ │
|
||
│ │ ◉ 842g / 1000g (67%) │
|
||
│ │──────────────────────────────────────────────│
|
||
│ │ Total: 1000g │ Remaining: 842g │ Diam: 1.75│
|
||
│ │ Dens: 1.24 │ Added: Mar 12 │ Last: Apr18│
|
||
│ │──────────────────────────────────────────────│
|
||
│ │ 📍 AMS Unit 2, Slot A3 [Move] │
|
||
│ │──────────────────────────────────────────────│
|
||
│ │ [Depleted] [Move Location] [Print] │
|
||
└──────┴──────────────────────────────────────────────┘
|
||
```
|
||
|
||
- **Horizontal layout advantage:** Metrics grid uses 3 columns on kiosk to fill width.
|
||
- **QR code and timeline:** Accessible via scroll or tab section below the fold.
|
||
- **Scrollable content area:** Hero + Metrics + Location fit above fold; QR + Timeline scroll into view.
|
||
- **Action row:** Sticky at bottom of scroll area, above Navigation Rail.
|
||
|
||
### Mobile PWA (375×812)
|
||
|
||
```
|
||
┌──────────────────────────────────┐
|
||
│ ← PLA Basic — Matte Black [✏] │
|
||
│──────────────────────────────────│
|
||
│ ┌──────┐ │
|
||
│ │SWATCH│ PLA Basic — Matte │
|
||
│ │ 80dp │ Black [Avail] │
|
||
│ └──────┘ Bambu Lab │
|
||
│ │
|
||
│ ◉ 842g / 1000g (67%) │
|
||
│──────────────────────────────────│
|
||
│ Total Weight │ Remaining │
|
||
│ 1,000g │ 842g (67%) │
|
||
│──────────────────────────────────│
|
||
│ Diameter │ Density │
|
||
│ 1.75mm │ 1.24 g/cm³ │
|
||
│──────────────────────────────────│
|
||
│ Date Added │ Last Used │
|
||
│ Mar 12, 2026 │ Apr 18, 2026 │
|
||
│──────────────────────────────────│
|
||
│ 📍 AMS Unit 2, Slot A3 [Move] │
|
||
│──────────────────────────────────│
|
||
│ ┌──────────┐ │
|
||
│ │ QR CODE │ │
|
||
│ │ 160dp │ EXT-2026-PLA-0042│
|
||
│ └──────────┘ [Reprint] │
|
||
│──────────────────────────────────│
|
||
│ Recent Usage │
|
||
│ Print #1847 — Benchy -32g │
|
||
│ Print #1842 — Housing -18g │
|
||
│ [View Full History →] │
|
||
│──────────────────────────────────│
|
||
│ [Depleted] [Move] [Print] │
|
||
│──────────────────────────────────│
|
||
│ 📦 🖨️ 📋 ⚙️ │
|
||
└──────────────────────────────────┘
|
||
```
|
||
|
||
- **Vertical scroll layout:** All sections stack vertically.
|
||
- **Metrics grid:** 2 columns on mobile (3 on kiosk).
|
||
- **Action row:** Sticky at bottom, above bottom navigation.
|
||
- **QR code:** Full-width card, scroll into view.
|
||
|
||
### Key Adaptations
|
||
|
||
| Property | Kiosk (800×480) | Mobile (375×812) |
|
||
|----------|-----------------|-------------------|
|
||
| Metrics columns | 3 (compact) | 2 (standard) |
|
||
| Hero section height | 180dp (compact) | 200dp (standard) |
|
||
| QR card position | Below fold, scroll | Below fold, scroll |
|
||
| Action row style | Larger buttons (56dp h) | Standard buttons (40dp h) |
|
||
| Timeline items visible | 2-3 | 3-4 |
|
||
| Move dialog | Center `mat-dialog` | Bottom sheet (`mat-bottom-sheet`) |
|
||
|
||
---
|
||
|
||
## 7. Developer Handoff Notes
|
||
|
||
### Angular Material Components
|
||
|
||
| UI Element | Angular Material Component | Notes |
|
||
|-----------|--------------------------|-------|
|
||
| Top App Bar | `<mat-toolbar>` | Collapsible title on scroll using `@angular/cdk/scrolling` |
|
||
| Color Swatch | Custom `div` | Circular, 80dp, `[style.backgroundColor]` binding |
|
||
| Circular Progress | `<mat-progress-spinner>` | `mode="determinate"`, `[value]` binding, custom color classes |
|
||
| Metrics Grid | CSS Grid inside `<mat-card>` | 2-col (mobile) / 3-col (kiosk) via CSS breakpoints |
|
||
| QR Code Card | `<mat-card>` elevated | Use `appearance="elevated"`. QR rendered via `qrcode` npm package or canvas |
|
||
| Location Card | `<mat-card>` outlined | Use `appearance="outlined"`. |
|
||
| Timeline | `<mat-list>` + `<mat-list-item>` | 2-line items with `matListItemIcon` for type icon |
|
||
| Action Buttons | `<button mat-button>` variants | Depleted: `mat-button` with `color="warn"`. Move: `mat-flat-button` with `color="accent"`. Print: `mat-raised-button` with `color="primary"` |
|
||
| Move Dialog | `<mat-dialog>` / `<mat-bottom-sheet>` | Responsive: dialog on kiosk, bottom sheet on mobile |
|
||
| Confirmation Dialog | `<mat-dialog>` | With `mat-dialog-actions`: Cancel + Confirm |
|
||
| Snackbar | `<mat-snack-bar>` | For success/error feedback on actions |
|
||
|
||
### Interaction Notes
|
||
|
||
1. **Collapsible title:** As user scrolls past hero, App Bar title animates from hidden to visible (standard M3 scroll behavior). Use `@angular/material` scroll dispatching.
|
||
2. **Progress ring animation:** On load, animate from 0 to actual value over 600ms with `ease-out`.
|
||
3. **QR code generation:** If `spool.qrCode` is null, show "Generate" button. On tap, call API to generate QR, then display.
|
||
4. **Reprint label:** Calls Bluetooth thermal printer service. Show snackbar: "Label sent to printer ✓" or "Printer not connected ✗".
|
||
5. **Move location dialog:** Show location tree (AMS units → slots, shelves). Selected location highlighted. Confirm → API call → snackbar confirmation.
|
||
6. **Mark Depleted:** Dialog: "Mark PLA Basic — Matte Black as depleted? This will update the spool's status and remove it from available inventory." Buttons: Cancel (text) / Mark Depleted (error filled).
|
||
7. **Delete spool:** Dialog: "Permanently delete PLA Basic — Matte Black? This cannot be undone." Buttons: Cancel (text) / Delete (error filled).
|
||
8. **Real-time updates:** Subscribe to `SpoolUpdated` SignalR event. If this spool's weight changes, animate the progress ring and update metrics in-place.
|
||
|
||
### Accessibility
|
||
|
||
| Requirement | Implementation |
|
||
|-------------|---------------|
|
||
| Screen reader (hero) | `aria-label="PLA Basic Matte Black by Bambu Lab, Available, 842 grams remaining of 1000 grams, 67 percent"` |
|
||
| Circular progress | `role="progressbar"`, `aria-valuenow="67"`, `aria-valuemin="0"`, `aria-valuemax="100"`, `aria-label="Remaining filament"` |
|
||
| Metrics grid | Semantic `<dl>` with `<dt>` (label) + `<dd>` (value), each with `aria-label` |
|
||
| QR code | `alt="QR code for spool EXT-2026-PLA-0042"`, `role="img"` |
|
||
| Color swatch | `aria-label="Filament color: Matte Black"`, `role="img"` |
|
||
| Action buttons | Clear `aria-label`: "Mark as depleted", "Move to new location", "Start print with this spool" |
|
||
| Confirmation dialogs | `aria-labelledby` for title, `aria-describedby` for description. Focus trap. Escape to close. |
|
||
| Keyboard nav | Tab order: Back → Edit → Overflow → Content sections → Action row. Enter to activate. |
|
||
| Focus on open | When navigating from inventory, focus lands on back button, then natural tab flow |
|
||
|
||
### SignalR Integration
|
||
|
||
- Subscribe to `SpoolUpdated` hub event, filter by current spool ID.
|
||
- On weight change: animate progress ring delta, update metrics, prepend usage timeline entry.
|
||
- On status change: update badge, adjust progress ring color, update action row buttons.
|
||
- On location change: update location card.
|
||
|
||
### Performance Notes
|
||
|
||
- Use `OnPush` change detection strategy for this component.
|
||
- QR code should be generated once and cached; don't regenerate on every change detection cycle.
|
||
- Usage timeline: load last 5 entries on init, lazy-load full history on "View Full History" tap. |