On the Settings page vehicle list, one vehicle shows "2022 Volkswagen null". The null should be replaced with a fallback like "Unknown Model" or hidden entirely. The mobile Vehicles page already shows "Unknown Model" for the same vehicle, so the fallback is inconsistent across views.
Acceptance Criteria
No null values displayed in vehicle names anywhere in the app
Consistent fallback text (e.g. "Unknown Model") used across Settings vehicle list, mobile Vehicles page, and any other vehicle name displays
Tested on mobile (320px, 768px) and desktop (1920px)
Relates to #162
## Severity: Critical
## Problem
On the Settings page vehicle list, one vehicle shows "2022 Volkswagen null". The `null` should be replaced with a fallback like "Unknown Model" or hidden entirely. The mobile Vehicles page already shows "Unknown Model" for the same vehicle, so the fallback is inconsistent across views.
## Acceptance Criteria
- No `null` values displayed in vehicle names anywhere in the app
- Consistent fallback text (e.g. "Unknown Model") used across Settings vehicle list, mobile Vehicles page, and any other vehicle name displays
- Tested on mobile (320px, 768px) and desktop (1920px)
Multiple locations across the frontend concatenate ${year} ${make} ${model} directly, resulting in "null" text when fields are missing. A shared utility exists in frontend/src/features/documents/utils/vehicleLabel.ts but is only used by the documents feature. This milestone promotes and extends that utility for project-wide use.
Implementation
1. Create frontend/src/core/utils/ directory (does not currently exist)
5. Documentation: After completion, add to frontend/README.md Structure section:
src/core/utils/vehicleDisplay.ts -- Shared vehicle display helpers: getVehicleLabel() (display name with fallback chain) and getVehicleSubtitle() (Year Make Model formatting). Used across vehicles, documents, dashboard, settings, and maintenance features.
Commit Convention
fix: promote vehicle display utils to core with null safety (refs #165)
Test Criteria
No null text visible anywhere in the UI
Consistent "Unknown Vehicle" or "Unknown Model" fallback when data is missing
Settings vehicle list, dashboard attention cards, and vehicle detail pages all display correctly
Verify on mobile (320px, 768px) and desktop (1920px) viewports
All existing document feature vehicle labels still work after import migration
Branch
Work on branch issue-162-ux-design-audit-cleanup (shared with all #162 sub-issues)
## Implementation Plan (from #162 -- Milestone 1)
**Phase**: 1 (Foundation) | **Priority**: Critical | **Depends on**: None | **Blocks**: #167, #171
### Context
Multiple locations across the frontend concatenate `${year} ${make} ${model}` directly, resulting in "null" text when fields are missing. A shared utility exists in `frontend/src/features/documents/utils/vehicleLabel.ts` but is only used by the documents feature. This milestone promotes and extends that utility for project-wide use.
### Implementation
**1. Create `frontend/src/core/utils/` directory** (does not currently exist)
**2. Create `frontend/src/core/utils/vehicleDisplay.ts`:**
```typescript
import { Vehicle } from '@/features/vehicles/types';
/** Primary display name with fallback chain: nickname -> year/make/model -> VIN -> ID */
export const getVehicleLabel = (vehicle: Vehicle | undefined): string => {
if (!vehicle) return 'Unknown Vehicle';
if (vehicle.nickname?.trim()) return vehicle.nickname.trim();
const parts = [vehicle.year, vehicle.make, vehicle.model, vehicle.trimLevel].filter(Boolean);
if (parts.length > 0) return parts.join(' ');
if (vehicle.vin) return vehicle.vin;
return vehicle.id ? `${vehicle.id.substring(0, 8)}...` : 'Unknown Vehicle';
};
/** Subtitle line: "Year Make Model" with null safety. Returns empty string if insufficient data. */
export const getVehicleSubtitle = (vehicle: Vehicle | undefined): string => {
if (!vehicle) return '';
const parts = [vehicle.year?.toString(), vehicle.make, vehicle.model].filter(Boolean);
return parts.length >= 2 ? parts.join(' ') : '';
};
```
**3. Delete** `frontend/src/features/documents/utils/vehicleLabel.ts` and update all imports to use the new location.
**4. Replace direct concatenation in these files:**
| File | Line(s) | Current Pattern | Change |
|------|---------|-----------------|--------|
| `frontend/src/pages/SettingsPage.tsx` | ~378 | `${year} ${make} ${model}` concat | Use `getVehicleSubtitle()` |
| `frontend/src/features/settings/mobile/MobileSettingsScreen.tsx` | ~376 | `${year} ${make} ${model}` concat | Use `getVehicleSubtitle()` |
| `frontend/src/features/dashboard/components/VehicleAttention.tsx` | ~107 | Direct concat | Use `getVehicleLabel()` |
| `frontend/src/features/vehicles/pages/VehicleDetailPage.tsx` | ~228 | `filter(Boolean)` pattern in displayName | Use `getVehicleLabel()` |
| `frontend/src/features/vehicles/pages/VehicleDetailPage.tsx` | ~376 | Direct concat in subtitle | Use `getVehicleSubtitle()` |
**5. Documentation**: After completion, add to `frontend/README.md` Structure section:
> `src/core/utils/vehicleDisplay.ts` -- Shared vehicle display helpers: `getVehicleLabel()` (display name with fallback chain) and `getVehicleSubtitle()` (Year Make Model formatting). Used across vehicles, documents, dashboard, settings, and maintenance features.
### Commit Convention
```
fix: promote vehicle display utils to core with null safety (refs #165)
```
### Test Criteria
- No `null` text visible anywhere in the UI
- Consistent "Unknown Vehicle" or "Unknown Model" fallback when data is missing
- Settings vehicle list, dashboard attention cards, and vehicle detail pages all display correctly
- Verify on mobile (320px, 768px) and desktop (1920px) viewports
- All existing document feature vehicle labels still work after import migration
### Branch
Work on branch `issue-162-ux-design-audit-cleanup` (shared with all #162 sub-issues)
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.
Relates to #162
Severity: Critical
Problem
On the Settings page vehicle list, one vehicle shows "2022 Volkswagen null". The
nullshould be replaced with a fallback like "Unknown Model" or hidden entirely. The mobile Vehicles page already shows "Unknown Model" for the same vehicle, so the fallback is inconsistent across views.Acceptance Criteria
nullvalues displayed in vehicle names anywhere in the appImplementation Plan (from #162 -- Milestone 1)
Phase: 1 (Foundation) | Priority: Critical | Depends on: None | Blocks: #167, #171
Context
Multiple locations across the frontend concatenate
${year} ${make} ${model}directly, resulting in "null" text when fields are missing. A shared utility exists infrontend/src/features/documents/utils/vehicleLabel.tsbut is only used by the documents feature. This milestone promotes and extends that utility for project-wide use.Implementation
1. Create
frontend/src/core/utils/directory (does not currently exist)2. Create
frontend/src/core/utils/vehicleDisplay.ts:3. Delete
frontend/src/features/documents/utils/vehicleLabel.tsand update all imports to use the new location.4. Replace direct concatenation in these files:
frontend/src/pages/SettingsPage.tsx${year} ${make} ${model}concatgetVehicleSubtitle()frontend/src/features/settings/mobile/MobileSettingsScreen.tsx${year} ${make} ${model}concatgetVehicleSubtitle()frontend/src/features/dashboard/components/VehicleAttention.tsxgetVehicleLabel()frontend/src/features/vehicles/pages/VehicleDetailPage.tsxfilter(Boolean)pattern in displayNamegetVehicleLabel()frontend/src/features/vehicles/pages/VehicleDetailPage.tsxgetVehicleSubtitle()5. Documentation: After completion, add to
frontend/README.mdStructure section:Commit Convention
Test Criteria
nulltext visible anywhere in the UIBranch
Work on branch
issue-162-ux-design-audit-cleanup(shared with all #162 sub-issues)Milestone: Execution Complete
Phase: Execution | Agent: Developer | Status: PASS
Changes Summary
Created:
frontend/src/core/utils/vehicleDisplay.tsVehicleLikeinterface for flexible type compatibilitygetVehicleLabel()-- primary display name with fallback chain: nickname -> year/make/model/trim -> VIN -> IDgetVehicleSubtitle()-- "Year Make Model" line with null safetyDeleted:
frontend/src/features/documents/utils/vehicleLabel.ts(promoted to core)Updated 17 consumer files replacing direct
${vehicle.year} ${vehicle.make} ${vehicle.model}concatenation:SettingsPage.tsx,MobileSettingsScreen.tsx-- Settings vehicle listVehicleAttention.tsx-- Dashboard attention cardsVehicleDetailPage.tsx-- Vehicle detail name + subtitleVehicleDetailMobile.tsx,VehicleMobileCard.tsx,VehicleCard.tsx-- Vehicle list/cardsMaintenancePage.tsx,MaintenanceMobileScreen.tsx-- Maintenance vehicle displayMaintenanceRecordForm.tsx,MaintenanceScheduleForm.tsx-- Form vehicle selectorsMaintenanceRecordEditDialog.tsx,MaintenanceScheduleEditDialog.tsx-- Edit dialogsResolveAssociationDialog.tsx-- Email ingestion vehicle associationVehicleSelectionDialog.tsx-- Subscription vehicle selectionAdminUsersMobileScreen.tsx-- Admin user vehicle listDocumentDetailPage.tsx,DocumentsMobileScreen.tsx,DocumentsPage.tsx-- Document imports migratedDocumentation: Updated
frontend/README.mdandfrontend/src/features/documents/CLAUDE.mdVerification
vehicleDisplay.tsCommit
325cf08--fix: promote vehicle display utils to core with null safety (refs #165)Verdict: PASS | Next: Visual verification on mobile/desktop viewports