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.
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
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
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
Button Rename: Changed "Open" to "View Details" on both desktop and mobile document list views for clearer UX intent.
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*
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
The Documents feature has a fragmented UX where metadata is hidden behind the Edit button:
Current workflow:
Issues:
Proposed Solution
1. Type-Specific Card Metadata
Display contextually relevant metadata on list cards based on document type:
2. Dedicated "View Details" Page
Replace the current preview-only page with a detail view that shows:
Layout:
3. Expiration Alerts (30-day warning)
Add visual indicators for documents expiring within 30 days:
Acceptance Criteria
Technical Notes
Screenshots
Current state documented during investigation - cards show minimal info, metadata only visible in Edit modal.
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 viewfrontend/src/features/documents/pages/DocumentDetailPage.tsx- Detail pagefrontend/src/features/documents/mobile/DocumentsMobileScreen.tsx- Mobile list viewfrontend/src/features/documents/components/DocumentForm.tsx- Type-specific field patternsfrontend/src/features/documents/types/documents.types.ts- Data structuresKey Findings:
expirationDatefield being availableNo Backend Changes Required -
DocumentRecordalready includesexpirationDate,issuedDate, anddetailsobject with all type-specific fields.Architecture Decision
Create 2 shared components to avoid duplication across 3 views:
ExpirationBadgeexpirationDate: string | nullDocumentCardMetadatadoc: DocumentRecord, variant: 'card' | 'detail' | 'mobile'Milestones
Milestone 1: Create ExpirationBadge Component
Scope: New component for expiration warnings
Files:
frontend/src/features/documents/components/ExpirationBadge.tsxfrontend/src/features/documents/components/ExpirationBadge.test.tsxImplementation:
expirationDate: string | null | undefined,className?: stringnullif no expiration dateAcceptance:
Milestone 2: Create DocumentCardMetadata Component
Scope: Shared component for type-specific metadata display
Files:
frontend/src/features/documents/components/DocumentCardMetadata.tsxfrontend/src/features/documents/components/DocumentCardMetadata.test.tsxImplementation:
doc: DocumentRecord,variant: 'card' | 'detail' | 'mobile'card: Compact, text-sm, max 3-4 fieldsmobile: Compact, text-xs, dark mode supportdetail: Full display, grid layoutAcceptance:
Milestone 3: Update DocumentsPage (Desktop List)
Scope: Add metadata and expiration badges to desktop cards
Files:
frontend/src/features/documents/pages/DocumentsPage.tsxImplementation:
Acceptance:
Milestone 4: Update DocumentsMobileScreen
Scope: Add metadata and expiration badges to mobile cards
Files:
frontend/src/features/documents/mobile/DocumentsMobileScreen.tsxImplementation:
Acceptance:
Milestone 5: Redesign DocumentDetailPage
Scope: Side-by-side layout with full metadata panel
Files:
frontend/src/features/documents/pages/DocumentDetailPage.tsxImplementation:
Desktop layout (md breakpoint and up):
Mobile layout (below md):
md:flex md:gap-6for side-by-sideAcceptance:
Milestone 6: Quality Assurance and Testing
Scope: Viewport testing, lint, type-check
Tasks:
npm run lint- fix all issuesnpm run type-check- fix all issuesnpm test- all tests passFiles Summary
frontend/src/features/documents/components/ExpirationBadge.tsxfrontend/src/features/documents/components/ExpirationBadge.test.tsxfrontend/src/features/documents/components/DocumentCardMetadata.tsxfrontend/src/features/documents/components/DocumentCardMetadata.test.tsxfrontend/src/features/documents/pages/DocumentsPage.tsxfrontend/src/features/documents/pages/DocumentDetailPage.tsxfrontend/src/features/documents/mobile/DocumentsMobileScreen.tsxTotal: 4 new files, 3 modified files
Dependencies
Risk Assessment
Verdict: AWAITING_REVIEW | Next: QR plan-completeness review
QR Review: Plan Completeness
Phase: Plan-Review | Agent: Quality Reviewer | Status: PASS
Checklist
Decision Log Review
Findings
None. Plan is complete and well-structured.
Considered But Not Flagged
Verdict: PASS | Next: TW plan-scrub
TW Review: Plan Scrub
Phase: Plan-Review | Agent: Technical Writer | Status: PASS
Documentation Quality Check
Terminology Consistency
Scrub Findings
Minor clarity improvement (not blocking):
Verified Against Codebase
DocumentRecordinterface confirmed atdocuments.types.ts:3-25dayjsimport pattern confirmed fromDocumentForm.tsx:9dark:text-avus,dark:text-titanioconfirmed in existing filesmin-h-[44px]pattern confirmed throughoutVerdict: PASS | Next: QR plan-code
QR Review: Plan Code
Phase: Plan-Review | Agent: Quality Reviewer | Status: PASS
RULE 0: Production Reliability
RULE 1: Project Conformance
features/documents/components/RULE 2: Structural Quality
Proposed Code Analysis
ExpirationBadge:
DocumentCardMetadata:
Layout Changes:
Findings
None. Proposed code follows all project standards.
Considered But Not Flagged
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 Docs
Phase: Plan-Review | Agent: Quality Reviewer | Status: PASS
Documentation Impact Assessment
Post-Implementation Documentation Needs
frontend/src/features/documents/README.mdCLAUDE.mddocs/Comment Quality Check
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
PLAN APPROVED - Ready to create branch and begin implementation.
Milestone: Implementation Complete
Phase: Execution | Agent: Developer | Status: PASS
Milestones Completed
Files Changed
frontend/src/features/documents/components/ExpirationBadge.tsxfrontend/src/features/documents/components/ExpirationBadge.test.tsxfrontend/src/features/documents/components/DocumentCardMetadata.tsxfrontend/src/features/documents/components/DocumentCardMetadata.test.tsxfrontend/src/features/documents/pages/DocumentsPage.tsxfrontend/src/features/documents/pages/DocumentDetailPage.tsxfrontend/src/features/documents/mobile/DocumentsMobileScreen.tsxfrontend/jest.config.ts(fixed testMatch pattern)Quality Checks
npm run lint- passes (pre-existing warnings only)npm run type-check- passesPR
PR #44: #44
Verdict: PASS | Next: Quality Agent final review
Fix: UX Improvements
Phase: Execution | Agent: Developer | Status: COMPLETE
Changes Made
DocumentsPage.tsxDocumentsMobileScreen.tsxDocumentDetailPage.tsxhasDisplayableMetadatahelper; conditionally render Details sectionDetails
Button Rename: Changed "Open" to "View Details" on both desktop and mobile document list views for clearer UX intent.
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
Commit
Ready for testing on staging after push