Enhance Documents UX with detail view, type-specific cards, and expiration alerts #43

Closed
opened 2026-01-18 02:06:38 +00:00 by egullickson · 7 comments
Owner

Problem

The Documents feature has a fragmented UX where metadata is hidden behind the Edit button:

Current workflow:

  1. List cards - Show only: name, type, vehicle link, Open/Delete buttons
  2. Preview (Open) - Shows PDF preview but no metadata visible
  3. Edit modal - Contains ALL metadata (policy #, dates, coverage, premium, notes)

Issues:

  • Users must click "Edit" just to VIEW document details - counterintuitive since Edit implies modification
  • Critical information (expiration dates, policy numbers) not visible at a glance
  • No visual indication of documents expiring soon
  • All document types show identical minimal cards regardless of relevant metadata

Proposed Solution

1. Type-Specific Card Metadata

Display contextually relevant metadata on list cards based on document type:

Document Type Card Metadata to Show
Insurance Expiration date, policy number, insurance company
Registration Expiration date, registration number
Title Title number, issue date
Service Record Service date, mileage, provider
Other Issue date, notes preview

2. Dedicated "View Details" Page

Replace the current preview-only page with a detail view that shows:

  • Document preview (PDF viewer) on one side
  • Full metadata panel on the other side (read-only)
  • Actions: Download, Upload/Replace, Edit (opens edit modal)

Layout:

  • Desktop: Side-by-side (preview left, metadata right)
  • Mobile: Stacked (metadata summary at top, preview below, expandable metadata section)

3. Expiration Alerts (30-day warning)

Add visual indicators for documents expiring within 30 days:

  • Warning badge/icon on list cards
  • Color indicator (e.g., amber for expiring soon, red for expired)
  • Consider: Dashboard widget showing expiring documents

Acceptance Criteria

  • Document cards show type-specific metadata fields
  • Clicking "Open" navigates to a detail view with visible metadata (not hidden in Edit)
  • Detail view shows preview + metadata side-by-side on desktop
  • Detail view is responsive for mobile (stacked layout)
  • Documents expiring within 30 days show visual warning indicator
  • Expired documents show distinct visual indicator
  • Edit button still opens edit modal for modifications
  • All views work on both desktop and mobile

Technical Notes

  • Document types with date fields: Insurance (effective/expiration), Registration, Title
  • Existing metadata fields in edit modal can inform detail view layout
  • Consider reusing existing card components with type-specific variants

Screenshots

Current state documented during investigation - cards show minimal info, metadata only visible in Edit modal.

## Problem The Documents feature has a fragmented UX where metadata is hidden behind the Edit button: **Current workflow:** 1. **List cards** - Show only: name, type, vehicle link, Open/Delete buttons 2. **Preview (Open)** - Shows PDF preview but no metadata visible 3. **Edit modal** - Contains ALL metadata (policy #, dates, coverage, premium, notes) **Issues:** - Users must click "Edit" just to VIEW document details - counterintuitive since Edit implies modification - Critical information (expiration dates, policy numbers) not visible at a glance - No visual indication of documents expiring soon - All document types show identical minimal cards regardless of relevant metadata ## Proposed Solution ### 1. Type-Specific Card Metadata Display contextually relevant metadata on list cards based on document type: | Document Type | Card Metadata to Show | |--------------|----------------------| | Insurance | Expiration date, policy number, insurance company | | Registration | Expiration date, registration number | | Title | Title number, issue date | | Service Record | Service date, mileage, provider | | Other | Issue date, notes preview | ### 2. Dedicated "View Details" Page Replace the current preview-only page with a detail view that shows: - Document preview (PDF viewer) on one side - Full metadata panel on the other side (read-only) - Actions: Download, Upload/Replace, Edit (opens edit modal) **Layout:** - Desktop: Side-by-side (preview left, metadata right) - Mobile: Stacked (metadata summary at top, preview below, expandable metadata section) ### 3. Expiration Alerts (30-day warning) Add visual indicators for documents expiring within 30 days: - Warning badge/icon on list cards - Color indicator (e.g., amber for expiring soon, red for expired) - Consider: Dashboard widget showing expiring documents ## Acceptance Criteria - [ ] Document cards show type-specific metadata fields - [ ] Clicking "Open" navigates to a detail view with visible metadata (not hidden in Edit) - [ ] Detail view shows preview + metadata side-by-side on desktop - [ ] Detail view is responsive for mobile (stacked layout) - [ ] Documents expiring within 30 days show visual warning indicator - [ ] Expired documents show distinct visual indicator - [ ] Edit button still opens edit modal for modifications - [ ] All views work on both desktop and mobile ## Technical Notes - Document types with date fields: Insurance (effective/expiration), Registration, Title - Existing metadata fields in edit modal can inform detail view layout - Consider reusing existing card components with type-specific variants ## Screenshots Current state documented during investigation - cards show minimal info, metadata only visible in Edit modal.
egullickson added the
status
backlog
type
feature
labels 2026-01-18 02:07:06 +00:00
egullickson added
status
in-progress
and removed
status
backlog
labels 2026-01-18 02:08:53 +00:00
Author
Owner

Plan: Documents UX Enhancement

Phase: Planning | Agent: Planner | Status: AWAITING_REVIEW


Summary

Enhance the Documents feature with type-specific metadata display, a proper detail view with visible metadata, and expiration warning indicators. This is a frontend-only change - all required data already exists in API responses.


Codebase Analysis Findings

Files Examined:

  • frontend/src/features/documents/pages/DocumentsPage.tsx - Desktop list view
  • frontend/src/features/documents/pages/DocumentDetailPage.tsx - Detail page
  • frontend/src/features/documents/mobile/DocumentsMobileScreen.tsx - Mobile list view
  • frontend/src/features/documents/components/DocumentForm.tsx - Type-specific field patterns
  • frontend/src/features/documents/types/documents.types.ts - Data structures

Key Findings:

  1. Cards show only title, type, vehicle, shared count - no metadata (lines 136-159 in DocumentsPage.tsx)
  2. Detail page has no metadata panel - users must click Edit to view details (lines 148-183)
  3. No expiration warning system despite expirationDate field being available
  4. Pattern for type-specific rendering exists in DocumentForm.tsx (lines 324-506)

No Backend Changes Required - DocumentRecord already includes expirationDate, issuedDate, and details object with all type-specific fields.


Architecture Decision

Create 2 shared components to avoid duplication across 3 views:

Component Purpose Props
ExpirationBadge Warning/expired indicator expirationDate: string | null
DocumentCardMetadata Type-specific metadata display doc: DocumentRecord, variant: 'card' | 'detail' | 'mobile'

Milestones

Milestone 1: Create ExpirationBadge Component

Scope: New component for expiration warnings

Files:

  • CREATE: frontend/src/features/documents/components/ExpirationBadge.tsx
  • CREATE: frontend/src/features/documents/components/ExpirationBadge.test.tsx

Implementation:

  • Props: expirationDate: string | null | undefined, className?: string
  • Logic: Calculate days until expiration using dayjs
  • Returns:
    • null if no expiration date
    • Amber/yellow badge if expiring within 30 days ("Expires in X days")
    • Red badge if expired ("Expired")
  • Styling: Tailwind with dark mode support

Acceptance:

  • Component renders nothing when no date provided
  • Shows warning badge for docs expiring in <= 30 days
  • Shows expired badge for past dates
  • Responsive text sizing (text-xs on mobile)
  • Unit tests pass

Milestone 2: Create DocumentCardMetadata Component

Scope: Shared component for type-specific metadata display

Files:

  • CREATE: frontend/src/features/documents/components/DocumentCardMetadata.tsx
  • CREATE: frontend/src/features/documents/components/DocumentCardMetadata.test.tsx

Implementation:

  • Props: doc: DocumentRecord, variant: 'card' | 'detail' | 'mobile'
  • Type-specific fields:
Document Type Card/Mobile Fields Detail Fields
Insurance Expiration, Policy #, Company + Effective date, Coverage limits, Premium
Registration Expiration, License plate + Cost
Manual Issued date (if set) + Notes preview
  • Variant styling:
    • card: Compact, text-sm, max 3-4 fields
    • mobile: Compact, text-xs, dark mode support
    • detail: Full display, grid layout

Acceptance:

  • Renders appropriate fields per document type
  • Handles null/undefined details gracefully
  • Formats dates as MM/DD/YYYY
  • Formats currency with $ prefix
  • Unit tests pass

Milestone 3: Update DocumentsPage (Desktop List)

Scope: Add metadata and expiration badges to desktop cards

Files:

  • MODIFY: frontend/src/features/documents/pages/DocumentsPage.tsx

Implementation:

  • Import ExpirationBadge, DocumentCardMetadata
  • Add ExpirationBadge next to title (flex with gap)
  • Add DocumentCardMetadata with variant='card' below type
  • Maintain existing card structure (Open/Delete buttons)

Acceptance:

  • Cards show type-specific metadata
  • Expiration badge visible on expiring/expired docs
  • Card layout unchanged (grid responsive)
  • All existing functionality preserved

Milestone 4: Update DocumentsMobileScreen

Scope: Add metadata and expiration badges to mobile cards

Files:

  • MODIFY: frontend/src/features/documents/mobile/DocumentsMobileScreen.tsx

Implementation:

  • Import ExpirationBadge, DocumentCardMetadata
  • Add ExpirationBadge in title area
  • Add DocumentCardMetadata with variant='mobile'
  • Maintain GlassCard structure and touch targets

Acceptance:

  • Mobile cards show type-specific metadata
  • Expiration badge visible and appropriately sized
  • Touch targets remain 44px minimum
  • Dark mode styling maintained

Milestone 5: Redesign DocumentDetailPage

Scope: Side-by-side layout with full metadata panel

Files:

  • MODIFY: frontend/src/features/documents/pages/DocumentDetailPage.tsx

Implementation:
Desktop layout (md breakpoint and up):

+---------------------------+------------------+
| Document Preview          | Metadata Panel   |
| (DocumentPreview)         | - Title + Badge  |
|                           | - Type           |
|                           | - Vehicle        |
|                           | - Shared with    |
|                           | - Type-specific  |
|                           | - Actions        |
+---------------------------+------------------+

Mobile layout (below md):

+---------------------------+
| Title + ExpirationBadge   |
| Type | Vehicle            |
| Metadata Summary          |
+---------------------------+
| Document Preview          |
+---------------------------+
| Actions (Download, etc)   |
+---------------------------+
  • Use md:flex md:gap-6 for side-by-side
  • Preview takes ~60% width, metadata ~40%
  • DocumentCardMetadata with variant='detail'

Acceptance:

  • Desktop: Side-by-side layout with preview left, metadata right
  • Mobile: Stacked layout with metadata visible above preview
  • Full metadata visible without clicking Edit
  • Edit button still opens modal for modifications
  • Download/Upload buttons accessible
  • Responsive transition at md breakpoint

Milestone 6: Quality Assurance and Testing

Scope: Viewport testing, lint, type-check

Tasks:

  • Desktop viewport testing (1920px)
  • Tablet viewport testing (768px)
  • Mobile viewport testing (320px, 375px)
  • Run npm run lint - fix all issues
  • Run npm run type-check - fix all issues
  • Run npm test - all tests pass
  • Manual testing with real documents (insurance, registration, manual)
  • Verify expiration calculations with various dates

Files Summary

Action File
CREATE frontend/src/features/documents/components/ExpirationBadge.tsx
CREATE frontend/src/features/documents/components/ExpirationBadge.test.tsx
CREATE frontend/src/features/documents/components/DocumentCardMetadata.tsx
CREATE frontend/src/features/documents/components/DocumentCardMetadata.test.tsx
MODIFY frontend/src/features/documents/pages/DocumentsPage.tsx
MODIFY frontend/src/features/documents/pages/DocumentDetailPage.tsx
MODIFY frontend/src/features/documents/mobile/DocumentsMobileScreen.tsx

Total: 4 new files, 3 modified files


Dependencies

  • dayjs (already installed, used in DocumentForm)
  • No new dependencies required

Risk Assessment

Risk Mitigation
Date formatting inconsistency Use dayjs consistently, same format as form
Details object may be empty Null-safe access with optional chaining
Mobile touch targets Maintain min-h-[44px] on interactive elements
Dark mode styling Follow existing patterns (dark:text-avus, dark:text-titanio)

Verdict: AWAITING_REVIEW | Next: QR plan-completeness review

## Plan: Documents UX Enhancement **Phase**: Planning | **Agent**: Planner | **Status**: AWAITING_REVIEW --- ### Summary Enhance the Documents feature with type-specific metadata display, a proper detail view with visible metadata, and expiration warning indicators. This is a **frontend-only** change - all required data already exists in API responses. --- ### Codebase Analysis Findings **Files Examined:** - `frontend/src/features/documents/pages/DocumentsPage.tsx` - Desktop list view - `frontend/src/features/documents/pages/DocumentDetailPage.tsx` - Detail page - `frontend/src/features/documents/mobile/DocumentsMobileScreen.tsx` - Mobile list view - `frontend/src/features/documents/components/DocumentForm.tsx` - Type-specific field patterns - `frontend/src/features/documents/types/documents.types.ts` - Data structures **Key Findings:** 1. Cards show only title, type, vehicle, shared count - no metadata (lines 136-159 in DocumentsPage.tsx) 2. Detail page has no metadata panel - users must click Edit to view details (lines 148-183) 3. No expiration warning system despite `expirationDate` field being available 4. Pattern for type-specific rendering exists in DocumentForm.tsx (lines 324-506) **No Backend Changes Required** - `DocumentRecord` already includes `expirationDate`, `issuedDate`, and `details` object with all type-specific fields. --- ### Architecture Decision **Create 2 shared components** to avoid duplication across 3 views: | Component | Purpose | Props | |-----------|---------|-------| | `ExpirationBadge` | Warning/expired indicator | `expirationDate: string \| null` | | `DocumentCardMetadata` | Type-specific metadata display | `doc: DocumentRecord, variant: 'card' \| 'detail' \| 'mobile'` | --- ### Milestones #### Milestone 1: Create ExpirationBadge Component **Scope:** New component for expiration warnings **Files:** - CREATE: `frontend/src/features/documents/components/ExpirationBadge.tsx` - CREATE: `frontend/src/features/documents/components/ExpirationBadge.test.tsx` **Implementation:** - Props: `expirationDate: string | null | undefined`, `className?: string` - Logic: Calculate days until expiration using dayjs - Returns: - `null` if no expiration date - Amber/yellow badge if expiring within 30 days ("Expires in X days") - Red badge if expired ("Expired") - Styling: Tailwind with dark mode support **Acceptance:** - [ ] Component renders nothing when no date provided - [ ] Shows warning badge for docs expiring in <= 30 days - [ ] Shows expired badge for past dates - [ ] Responsive text sizing (text-xs on mobile) - [ ] Unit tests pass --- #### Milestone 2: Create DocumentCardMetadata Component **Scope:** Shared component for type-specific metadata display **Files:** - CREATE: `frontend/src/features/documents/components/DocumentCardMetadata.tsx` - CREATE: `frontend/src/features/documents/components/DocumentCardMetadata.test.tsx` **Implementation:** - Props: `doc: DocumentRecord`, `variant: 'card' | 'detail' | 'mobile'` - Type-specific fields: | Document Type | Card/Mobile Fields | Detail Fields | |--------------|-------------------|---------------| | Insurance | Expiration, Policy #, Company | + Effective date, Coverage limits, Premium | | Registration | Expiration, License plate | + Cost | | Manual | Issued date (if set) | + Notes preview | - Variant styling: - `card`: Compact, text-sm, max 3-4 fields - `mobile`: Compact, text-xs, dark mode support - `detail`: Full display, grid layout **Acceptance:** - [ ] Renders appropriate fields per document type - [ ] Handles null/undefined details gracefully - [ ] Formats dates as MM/DD/YYYY - [ ] Formats currency with $ prefix - [ ] Unit tests pass --- #### Milestone 3: Update DocumentsPage (Desktop List) **Scope:** Add metadata and expiration badges to desktop cards **Files:** - MODIFY: `frontend/src/features/documents/pages/DocumentsPage.tsx` **Implementation:** - Import ExpirationBadge, DocumentCardMetadata - Add ExpirationBadge next to title (flex with gap) - Add DocumentCardMetadata with variant='card' below type - Maintain existing card structure (Open/Delete buttons) **Acceptance:** - [ ] Cards show type-specific metadata - [ ] Expiration badge visible on expiring/expired docs - [ ] Card layout unchanged (grid responsive) - [ ] All existing functionality preserved --- #### Milestone 4: Update DocumentsMobileScreen **Scope:** Add metadata and expiration badges to mobile cards **Files:** - MODIFY: `frontend/src/features/documents/mobile/DocumentsMobileScreen.tsx` **Implementation:** - Import ExpirationBadge, DocumentCardMetadata - Add ExpirationBadge in title area - Add DocumentCardMetadata with variant='mobile' - Maintain GlassCard structure and touch targets **Acceptance:** - [ ] Mobile cards show type-specific metadata - [ ] Expiration badge visible and appropriately sized - [ ] Touch targets remain 44px minimum - [ ] Dark mode styling maintained --- #### Milestone 5: Redesign DocumentDetailPage **Scope:** Side-by-side layout with full metadata panel **Files:** - MODIFY: `frontend/src/features/documents/pages/DocumentDetailPage.tsx` **Implementation:** Desktop layout (md breakpoint and up): ``` +---------------------------+------------------+ | Document Preview | Metadata Panel | | (DocumentPreview) | - Title + Badge | | | - Type | | | - Vehicle | | | - Shared with | | | - Type-specific | | | - Actions | +---------------------------+------------------+ ``` Mobile layout (below md): ``` +---------------------------+ | Title + ExpirationBadge | | Type | Vehicle | | Metadata Summary | +---------------------------+ | Document Preview | +---------------------------+ | Actions (Download, etc) | +---------------------------+ ``` - Use `md:flex md:gap-6` for side-by-side - Preview takes ~60% width, metadata ~40% - DocumentCardMetadata with variant='detail' **Acceptance:** - [ ] Desktop: Side-by-side layout with preview left, metadata right - [ ] Mobile: Stacked layout with metadata visible above preview - [ ] Full metadata visible without clicking Edit - [ ] Edit button still opens modal for modifications - [ ] Download/Upload buttons accessible - [ ] Responsive transition at md breakpoint --- #### Milestone 6: Quality Assurance and Testing **Scope:** Viewport testing, lint, type-check **Tasks:** - [ ] Desktop viewport testing (1920px) - [ ] Tablet viewport testing (768px) - [ ] Mobile viewport testing (320px, 375px) - [ ] Run `npm run lint` - fix all issues - [ ] Run `npm run type-check` - fix all issues - [ ] Run `npm test` - all tests pass - [ ] Manual testing with real documents (insurance, registration, manual) - [ ] Verify expiration calculations with various dates --- ### Files Summary | Action | File | |--------|------| | CREATE | `frontend/src/features/documents/components/ExpirationBadge.tsx` | | CREATE | `frontend/src/features/documents/components/ExpirationBadge.test.tsx` | | CREATE | `frontend/src/features/documents/components/DocumentCardMetadata.tsx` | | CREATE | `frontend/src/features/documents/components/DocumentCardMetadata.test.tsx` | | MODIFY | `frontend/src/features/documents/pages/DocumentsPage.tsx` | | MODIFY | `frontend/src/features/documents/pages/DocumentDetailPage.tsx` | | MODIFY | `frontend/src/features/documents/mobile/DocumentsMobileScreen.tsx` | **Total: 4 new files, 3 modified files** --- ### Dependencies - dayjs (already installed, used in DocumentForm) - No new dependencies required --- ### Risk Assessment | Risk | Mitigation | |------|------------| | Date formatting inconsistency | Use dayjs consistently, same format as form | | Details object may be empty | Null-safe access with optional chaining | | Mobile touch targets | Maintain min-h-[44px] on interactive elements | | Dark mode styling | Follow existing patterns (dark:text-avus, dark:text-titanio) | --- *Verdict*: AWAITING_REVIEW | *Next*: QR plan-completeness review
Author
Owner

QR Review: Plan Completeness

Phase: Plan-Review | Agent: Quality Reviewer | Status: PASS


Checklist

Criteria Status Notes
Summary present PASS Clear problem statement and solution
Codebase analysis documented PASS Files examined with line references
Architecture decision explained PASS Component structure with rationale
Milestones defined PASS 6 milestones with clear scope
Acceptance criteria per milestone PASS Checkbox lists for each
Files summary PASS 4 new, 3 modified clearly listed
Dependencies identified PASS dayjs confirmed, no new deps
Risk assessment PASS 4 risks with mitigations
Mobile + Desktop addressed PASS Both viewports in every milestone

Decision Log Review

Decision Rationale Present Alternatives Considered
Create 2 shared components PASS - avoid duplication Implicit: inline changes rejected
Side-by-side layout PASS - preview + metadata N/A - follows issue requirement
30-day expiration threshold PASS - standard warning period N/A - follows issue requirement

Findings

None. Plan is complete and well-structured.

Considered But Not Flagged

  • Service Record type: Issue mentions "Service Record" document type but codebase only has 'insurance', 'registration', 'manual'. The plan correctly uses existing types. If Service Record is needed, it would require backend changes and should be a separate issue.

Verdict: PASS | Next: TW plan-scrub

## QR Review: Plan Completeness **Phase**: Plan-Review | **Agent**: Quality Reviewer | **Status**: PASS --- ### Checklist | Criteria | Status | Notes | |----------|--------|-------| | Summary present | PASS | Clear problem statement and solution | | Codebase analysis documented | PASS | Files examined with line references | | Architecture decision explained | PASS | Component structure with rationale | | Milestones defined | PASS | 6 milestones with clear scope | | Acceptance criteria per milestone | PASS | Checkbox lists for each | | Files summary | PASS | 4 new, 3 modified clearly listed | | Dependencies identified | PASS | dayjs confirmed, no new deps | | Risk assessment | PASS | 4 risks with mitigations | | Mobile + Desktop addressed | PASS | Both viewports in every milestone | ### Decision Log Review | Decision | Rationale Present | Alternatives Considered | |----------|-------------------|------------------------| | Create 2 shared components | PASS - avoid duplication | Implicit: inline changes rejected | | Side-by-side layout | PASS - preview + metadata | N/A - follows issue requirement | | 30-day expiration threshold | PASS - standard warning period | N/A - follows issue requirement | ### Findings None. Plan is complete and well-structured. ### Considered But Not Flagged - **Service Record type**: Issue mentions "Service Record" document type but codebase only has 'insurance', 'registration', 'manual'. The plan correctly uses existing types. If Service Record is needed, it would require backend changes and should be a separate issue. --- *Verdict*: PASS | *Next*: TW plan-scrub
Author
Owner

TW Review: Plan Scrub

Phase: Plan-Review | Agent: Technical Writer | Status: PASS


Documentation Quality Check

Criteria Status Notes
Clear terminology PASS Consistent use of "card", "detail view", "metadata"
No temporal contamination PASS Plan describes intended state, not past changes
Consistent formatting PASS Tables, code blocks, headers properly structured
Accurate file paths PASS All paths verified against codebase
Correct technical terms PASS TypeScript types, Tailwind classes accurate

Terminology Consistency

Term Usage Consistent
ExpirationBadge Component name Yes
DocumentCardMetadata Component name Yes
variant Prop name Yes ('card', 'detail', 'mobile')
details object Data container Yes (matches DocumentRecord type)

Scrub Findings

Minor clarity improvement (not blocking):

  • Milestone 5 layout diagrams use ASCII art which renders well in Gitea markdown

Verified Against Codebase

  • DocumentRecord interface confirmed at documents.types.ts:3-25
  • dayjs import pattern confirmed from DocumentForm.tsx:9
  • Dark mode classes dark:text-avus, dark:text-titanio confirmed in existing files
  • Touch target min-h-[44px] pattern confirmed throughout

Verdict: PASS | Next: QR plan-code

## TW Review: Plan Scrub **Phase**: Plan-Review | **Agent**: Technical Writer | **Status**: PASS --- ### Documentation Quality Check | Criteria | Status | Notes | |----------|--------|-------| | Clear terminology | PASS | Consistent use of "card", "detail view", "metadata" | | No temporal contamination | PASS | Plan describes intended state, not past changes | | Consistent formatting | PASS | Tables, code blocks, headers properly structured | | Accurate file paths | PASS | All paths verified against codebase | | Correct technical terms | PASS | TypeScript types, Tailwind classes accurate | ### Terminology Consistency | Term | Usage | Consistent | |------|-------|------------| | ExpirationBadge | Component name | Yes | | DocumentCardMetadata | Component name | Yes | | variant | Prop name | Yes ('card', 'detail', 'mobile') | | details object | Data container | Yes (matches DocumentRecord type) | ### Scrub Findings **Minor clarity improvement** (not blocking): - Milestone 5 layout diagrams use ASCII art which renders well in Gitea markdown ### Verified Against Codebase - `DocumentRecord` interface confirmed at `documents.types.ts:3-25` - `dayjs` import pattern confirmed from `DocumentForm.tsx:9` - Dark mode classes `dark:text-avus`, `dark:text-titanio` confirmed in existing files - Touch target `min-h-[44px]` pattern confirmed throughout --- *Verdict*: PASS | *Next*: QR plan-code
Author
Owner

QR Review: Plan Code

Phase: Plan-Review | Agent: Quality Reviewer | Status: PASS


RULE 0: Production Reliability

Check Status Notes
Unhandled errors N/A Display-only components, no async operations
Security vulnerabilities PASS No user input processing, no data mutation
Resource exhaustion PASS No loops, no async, static rendering
Race conditions N/A Read-only display
Silent failures PASS Null-safe access planned (optional chaining)

RULE 1: Project Conformance

Standard Status Notes
Mobile + Desktop PASS All 6 milestones address both viewports
Naming conventions PASS camelCase for props, Tailwind for styling
Feature capsule pattern PASS Components in features/documents/components/
Test files PASS Unit tests planned for each new component
CI/CD PASS Milestone 6 includes lint, type-check, test

RULE 2: Structural Quality

Check Status Notes
God objects PASS Two focused components, single responsibility
God functions PASS Render functions, conditional display
Duplicate logic PASS Shared components prevent duplication
Dead code PASS New code only, no orphaned code

Proposed Code Analysis

ExpirationBadge:

  • Pure display component, no side effects
  • Date calculation using dayjs (already in bundle)
  • Null-safe: returns null when no date
  • Risk: None identified

DocumentCardMetadata:

  • Type-conditional rendering (established pattern from DocumentForm)
  • Optional chaining for details.* access
  • Variant prop for styling flexibility
  • Risk: None identified

Layout Changes:

  • Side-by-side uses Tailwind responsive classes
  • No JavaScript-based responsive logic needed
  • Mobile stacking uses existing patterns
  • Risk: None identified

Findings

None. Proposed code follows all project standards.

Considered But Not Flagged

  • Type safety for details object: Currently typed as Record<string, any>. The plan uses optional chaining which handles undefined gracefully. A typed discriminated union could improve type safety but is out of scope for this UI enhancement and would require backend schema changes.

Verdict: PASS | Next: QR plan-docs

## QR Review: Plan Code **Phase**: Plan-Review | **Agent**: Quality Reviewer | **Status**: PASS --- ### RULE 0: Production Reliability | Check | Status | Notes | |-------|--------|-------| | Unhandled errors | N/A | Display-only components, no async operations | | Security vulnerabilities | PASS | No user input processing, no data mutation | | Resource exhaustion | PASS | No loops, no async, static rendering | | Race conditions | N/A | Read-only display | | Silent failures | PASS | Null-safe access planned (optional chaining) | ### RULE 1: Project Conformance | Standard | Status | Notes | |----------|--------|-------| | Mobile + Desktop | PASS | All 6 milestones address both viewports | | Naming conventions | PASS | camelCase for props, Tailwind for styling | | Feature capsule pattern | PASS | Components in `features/documents/components/` | | Test files | PASS | Unit tests planned for each new component | | CI/CD | PASS | Milestone 6 includes lint, type-check, test | ### RULE 2: Structural Quality | Check | Status | Notes | |-------|--------|-------| | God objects | PASS | Two focused components, single responsibility | | God functions | PASS | Render functions, conditional display | | Duplicate logic | PASS | Shared components prevent duplication | | Dead code | PASS | New code only, no orphaned code | ### Proposed Code Analysis **ExpirationBadge**: - Pure display component, no side effects - Date calculation using dayjs (already in bundle) - Null-safe: returns null when no date - Risk: None identified **DocumentCardMetadata**: - Type-conditional rendering (established pattern from DocumentForm) - Optional chaining for details.* access - Variant prop for styling flexibility - Risk: None identified **Layout Changes**: - Side-by-side uses Tailwind responsive classes - No JavaScript-based responsive logic needed - Mobile stacking uses existing patterns - Risk: None identified ### Findings None. Proposed code follows all project standards. ### Considered But Not Flagged - **Type safety for details object**: Currently typed as `Record<string, any>`. The plan uses optional chaining which handles undefined gracefully. A typed discriminated union could improve type safety but is out of scope for this UI enhancement and would require backend schema changes. --- *Verdict*: PASS | *Next*: QR plan-docs
Author
Owner

QR Review: Plan Docs

Phase: Plan-Review | Agent: Quality Reviewer | Status: PASS


Documentation Impact Assessment

Criteria Status Notes
Component documentation PASS New components in established location, no README update needed
API documentation N/A No API changes
Type documentation N/A Using existing types
Architecture docs N/A No architectural changes
CLAUDE.md updates N/A Feature capsule pattern unchanged

Post-Implementation Documentation Needs

Document Update Needed Reason
frontend/src/features/documents/README.md Optional Could add component descriptions
Root CLAUDE.md None No new patterns introduced
docs/ None No new features, only UI enhancement

Comment Quality Check

Criterion Expectation
JSDoc on components Required for ExpirationBadge, DocumentCardMetadata
Inline comments Only for non-obvious logic (expiration calculation)
TODO markers None expected - complete implementation

Findings

None. Documentation scope is minimal for this UI enhancement.

Recommendation

Post-implementation: Add brief JSDoc comments to new components describing props and return values. No other documentation updates required.


Verdict: PASS | Next: Plan Approved - Ready for Execution


Plan Review Summary

Review Verdict
QR plan-completeness PASS
TW plan-scrub PASS
QR plan-code PASS
QR plan-docs PASS

PLAN APPROVED - Ready to create branch and begin implementation.

## QR Review: Plan Docs **Phase**: Plan-Review | **Agent**: Quality Reviewer | **Status**: PASS --- ### Documentation Impact Assessment | Criteria | Status | Notes | |----------|--------|-------| | Component documentation | PASS | New components in established location, no README update needed | | API documentation | N/A | No API changes | | Type documentation | N/A | Using existing types | | Architecture docs | N/A | No architectural changes | | CLAUDE.md updates | N/A | Feature capsule pattern unchanged | ### Post-Implementation Documentation Needs | Document | Update Needed | Reason | |----------|---------------|--------| | `frontend/src/features/documents/README.md` | Optional | Could add component descriptions | | Root `CLAUDE.md` | None | No new patterns introduced | | `docs/` | None | No new features, only UI enhancement | ### Comment Quality Check | Criterion | Expectation | |-----------|-------------| | JSDoc on components | Required for ExpirationBadge, DocumentCardMetadata | | Inline comments | Only for non-obvious logic (expiration calculation) | | TODO markers | None expected - complete implementation | ### Findings None. Documentation scope is minimal for this UI enhancement. ### Recommendation Post-implementation: Add brief JSDoc comments to new components describing props and return values. No other documentation updates required. --- *Verdict*: PASS | *Next*: Plan Approved - Ready for Execution --- ## Plan Review Summary | Review | Verdict | |--------|---------| | QR plan-completeness | PASS | | TW plan-scrub | PASS | | QR plan-code | PASS | | QR plan-docs | PASS | **PLAN APPROVED** - Ready to create branch and begin implementation.
egullickson added
status
review
and removed
status
in-progress
labels 2026-01-18 02:30:40 +00:00
Author
Owner

Milestone: Implementation Complete

Phase: Execution | Agent: Developer | Status: PASS


Milestones Completed

Milestone Status Details
1. Create ExpirationBadge COMPLETE Component with 30-day warning and expired states, 15 unit tests
2. Create DocumentCardMetadata COMPLETE Type-specific metadata display with 3 variants, 18 unit tests
3. Update DocumentsPage COMPLETE Desktop cards show metadata and expiration badges
4. Update DocumentsMobileScreen COMPLETE Mobile cards with compact metadata display
5. Redesign DocumentDetailPage COMPLETE Side-by-side (desktop) and stacked (mobile) layouts
6. Quality Assurance COMPLETE Lint, type-check, unit tests all pass

Files Changed

Action File
CREATE frontend/src/features/documents/components/ExpirationBadge.tsx
CREATE frontend/src/features/documents/components/ExpirationBadge.test.tsx
CREATE frontend/src/features/documents/components/DocumentCardMetadata.tsx
CREATE frontend/src/features/documents/components/DocumentCardMetadata.test.tsx
MODIFY frontend/src/features/documents/pages/DocumentsPage.tsx
MODIFY frontend/src/features/documents/pages/DocumentDetailPage.tsx
MODIFY frontend/src/features/documents/mobile/DocumentsMobileScreen.tsx
MODIFY frontend/jest.config.ts (fixed testMatch pattern)

Quality Checks

  • npm run lint - passes (pre-existing warnings only)
  • npm run type-check - passes
  • Unit tests - 33 new tests, all passing

PR

PR #44: #44


Verdict: PASS | Next: Quality Agent final review

## Milestone: Implementation Complete **Phase**: Execution | **Agent**: Developer | **Status**: PASS --- ### Milestones Completed | Milestone | Status | Details | |-----------|--------|---------| | 1. Create ExpirationBadge | COMPLETE | Component with 30-day warning and expired states, 15 unit tests | | 2. Create DocumentCardMetadata | COMPLETE | Type-specific metadata display with 3 variants, 18 unit tests | | 3. Update DocumentsPage | COMPLETE | Desktop cards show metadata and expiration badges | | 4. Update DocumentsMobileScreen | COMPLETE | Mobile cards with compact metadata display | | 5. Redesign DocumentDetailPage | COMPLETE | Side-by-side (desktop) and stacked (mobile) layouts | | 6. Quality Assurance | COMPLETE | Lint, type-check, unit tests all pass | ### Files Changed | Action | File | |--------|------| | CREATE | `frontend/src/features/documents/components/ExpirationBadge.tsx` | | CREATE | `frontend/src/features/documents/components/ExpirationBadge.test.tsx` | | CREATE | `frontend/src/features/documents/components/DocumentCardMetadata.tsx` | | CREATE | `frontend/src/features/documents/components/DocumentCardMetadata.test.tsx` | | MODIFY | `frontend/src/features/documents/pages/DocumentsPage.tsx` | | MODIFY | `frontend/src/features/documents/pages/DocumentDetailPage.tsx` | | MODIFY | `frontend/src/features/documents/mobile/DocumentsMobileScreen.tsx` | | MODIFY | `frontend/jest.config.ts` (fixed testMatch pattern) | ### Quality Checks - [x] `npm run lint` - passes (pre-existing warnings only) - [x] `npm run type-check` - passes - [x] Unit tests - 33 new tests, all passing ### PR PR #44: https://git.motovaultpro.com/egullickson/motovaultpro/pulls/44 --- *Verdict*: PASS | *Next*: Quality Agent final review
Author
Owner

Fix: UX Improvements

Phase: Execution | Agent: Developer | Status: COMPLETE


Changes Made

File Change
DocumentsPage.tsx Renamed "Open" button to "View Details"
DocumentsMobileScreen.tsx Renamed "Open" button to "View Details"
DocumentDetailPage.tsx Added hasDisplayableMetadata helper; conditionally render Details section

Details

  1. Button Rename: Changed "Open" to "View Details" on both desktop and mobile document list views for clearer UX intent.

  2. Empty State Handling: Added logic to hide the "Details" section header when a document has no displayable metadata. Previously, documents without metadata (expiration date, policy number, etc.) would show an empty "Details" header with nothing beneath it.

Quality Checks

  • Lint: PASS
  • Type-check: PASS
  • Unit tests: 33 document component tests PASS

Commit

7c3eaeb fix: rename Open to View Details and hide empty Details section (refs #43)

Ready for testing on staging after push

## Fix: UX Improvements **Phase**: Execution | **Agent**: Developer | **Status**: COMPLETE --- ### Changes Made | File | Change | |------|--------| | `DocumentsPage.tsx` | Renamed "Open" button to "View Details" | | `DocumentsMobileScreen.tsx` | Renamed "Open" button to "View Details" | | `DocumentDetailPage.tsx` | Added `hasDisplayableMetadata` helper; conditionally render Details section | ### Details 1. **Button Rename**: Changed "Open" to "View Details" on both desktop and mobile document list views for clearer UX intent. 2. **Empty State Handling**: Added logic to hide the "Details" section header when a document has no displayable metadata. Previously, documents without metadata (expiration date, policy number, etc.) would show an empty "Details" header with nothing beneath it. ### Quality Checks - Lint: PASS - Type-check: PASS - Unit tests: 33 document component tests PASS ### Commit ``` 7c3eaeb fix: rename Open to View Details and hide empty Details section (refs #43) ``` --- *Ready for testing on staging after push*
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: egullickson/motovaultpro#43