feat: display vehicle names instead of UUIDs in document views (refs #31)

- Created shared utility getVehicleLabel() for consistent vehicle display
- Updated DocumentsPage to show vehicle names with clickable links
- Added "Shared with X vehicles" indicator for multi-vehicle docs
- Updated DocumentDetailPage with vehicle name and shared vehicle list
- Updated DocumentsMobileScreen with vehicle names and "Shared" indicator
- All vehicle names link to vehicle detail pages
- Mobile-first with 44px touch targets on all links

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Eric Gullickson
2026-01-14 19:34:02 -06:00
parent e558fdf8f9
commit 8968cad805
4 changed files with 103 additions and 20 deletions

View File

@@ -1,4 +1,4 @@
import React, { useRef } from 'react';
import React, { useRef, useMemo } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { useAuth0 } from '@auth0/auth0-react';
import { isAxiosError } from 'axios';
@@ -8,15 +8,21 @@ import { useDocument } from '../hooks/useDocuments';
import { useUploadWithProgress } from '../hooks/useUploadWithProgress';
import { documentsApi } from '../api/documents.api';
import { DocumentPreview } from '../components/DocumentPreview';
import { useVehicle, useVehicles } from '../../vehicles/hooks/useVehicles';
import { getVehicleLabel } from '../utils/vehicleLabel';
export const DocumentDetailPage: React.FC = () => {
const { id } = useParams<{ id: string }>();
const navigate = useNavigate();
const { isAuthenticated, isLoading: authLoading, loginWithRedirect } = useAuth0();
const { data: doc, isLoading, error } = useDocument(id);
const { data: vehicle } = useVehicle(doc?.vehicleId || '');
const { data: vehicles } = useVehicles();
const inputRef = useRef<HTMLInputElement | null>(null);
const upload = useUploadWithProgress(id!);
const vehiclesMap = useMemo(() => new Map(vehicles?.map(v => [v.id, v]) || []), [vehicles]);
const handleDownload = async () => {
if (!id) return;
const blob = await documentsApi.download(id);
@@ -141,7 +147,35 @@ export const DocumentDetailPage: React.FC = () => {
<div className="p-4 space-y-2">
<h2 className="text-xl font-semibold">{doc.title}</h2>
<div className="text-sm text-slate-500">Type: {doc.documentType}</div>
<div className="text-sm text-slate-500">Vehicle: {doc.vehicleId}</div>
<div className="text-sm">
<span className="text-slate-500">Vehicle: </span>
<button
onClick={() => navigate(`/garage/vehicles/${doc.vehicleId}`)}
className="text-blue-600 hover:text-blue-800 underline min-h-[44px] inline-flex items-center"
>
{getVehicleLabel(vehicle)}
</button>
</div>
{doc.sharedVehicleIds.length > 0 && (
<div className="text-sm text-slate-500 space-y-1">
<div className="font-medium">Shared with:</div>
<ul className="list-disc list-inside pl-2">
{doc.sharedVehicleIds.map((vehicleId) => {
const sharedVehicle = vehiclesMap.get(vehicleId);
return (
<li key={vehicleId}>
<button
onClick={() => navigate(`/garage/vehicles/${vehicleId}`)}
className="text-blue-600 hover:text-blue-800 underline min-h-[44px] inline-flex items-center"
>
{getVehicleLabel(sharedVehicle)}
</button>
</li>
);
})}
</ul>
</div>
)}
<div className="pt-2">
<DocumentPreview doc={doc} />
</div>