UX Improvements

This commit is contained in:
Eric Gullickson
2025-09-26 14:45:03 -05:00
parent 56443d5b2f
commit 2e1b588270
13 changed files with 389 additions and 97 deletions

View File

@@ -3,7 +3,7 @@
*/
import React, { useMemo, useState } from 'react';
import { Box, Typography, Button, Card, CardContent, Divider, FormControl, InputLabel, Select, MenuItem, List, ListItem, ListItemText } from '@mui/material';
import { Box, Typography, Button, Card, CardContent, Divider, FormControl, InputLabel, Select, MenuItem, List, ListItem } from '@mui/material';
import { useQueryClient } from '@tanstack/react-query';
import { Vehicle } from '../types/vehicles.types';
import { useFuelLogs } from '../../fuel-logs/hooks/useFuelLogs';
@@ -57,6 +57,7 @@ export const VehicleDetailMobile: React.FC<VehicleDetailMobileProps> = ({
const { fuelLogs, isLoading: isFuelLoading } = useFuelLogs(vehicle.id);
const queryClient = useQueryClient();
const [editingLog, setEditingLog] = useState<FuelLogResponse | null>(null);
// Unit conversions are now handled by the backend
type VehicleRecord = {
id: string;
@@ -64,19 +65,71 @@ export const VehicleDetailMobile: React.FC<VehicleDetailMobileProps> = ({
date: string; // ISO
summary: string;
amount?: string;
secondary?: string;
};
const records: VehicleRecord[] = useMemo(() => {
const list: VehicleRecord[] = [];
if (fuelLogs && Array.isArray(fuelLogs)) {
// Build a map of prior odometer readings to compute trip distance when missing
const logsAsc = [...(fuelLogs as FuelLogResponse[])].sort(
(a, b) => new Date(a.dateTime).getTime() - new Date(b.dateTime).getTime()
);
const prevOdoById = new Map<string, number | undefined>();
let lastOdo: number | undefined = undefined;
for (const l of logsAsc) {
prevOdoById.set(l.id, lastOdo);
if (typeof l.odometerReading === 'number' && !isNaN(l.odometerReading)) {
lastOdo = l.odometerReading;
}
}
for (const log of fuelLogs as FuelLogResponse[]) {
const parts: string[] = [];
if (log.fuelUnits) parts.push(`${Number(log.fuelUnits).toFixed(3)} units`);
if (log.fuelType) parts.push(`${log.fuelType}${log.fuelGrade ? ' ' + log.fuelGrade : ''}`);
if (log.efficiencyLabel) parts.push(log.efficiencyLabel);
const summary = parts.join(' • ');
// Use efficiency from API response (backend calculates this properly)
let efficiency = '';
if (typeof log.efficiency === 'number' && log.efficiency > 0) {
// DEBUG: Log what the backend is actually returning
console.log('🔍 Fuel Log API Response:', {
efficiency: log.efficiency,
efficiencyLabel: log.efficiencyLabel,
logId: log.id
});
// Backend returns efficiency in correct units based on user preference
efficiency = `${log.efficiencyLabel || 'MPG'}: ${log.efficiency.toFixed(3)}`;
}
// Secondary line components
const secondaryParts: string[] = [];
// Grade label (prefer grade only)
if (log.fuelGrade) {
secondaryParts.push(`Grade: ${log.fuelGrade}`);
} else if (log.fuelType) {
const ft = String(log.fuelType);
secondaryParts.push(ft.charAt(0).toUpperCase() + ft.slice(1));
}
// Date
secondaryParts.push(new Date(log.dateTime).toLocaleDateString());
// Type
secondaryParts.push('Fuel Log');
const summary = efficiency; // Primary line shows MPG/km/L from backend
const secondary = secondaryParts.join(' • '); // Secondary line shows Grade • Date • Type
const amount = (typeof log.totalCost === 'number') ? `$${log.totalCost.toFixed(2)}` : undefined;
list.push({ id: log.id, type: 'Fuel Logs', date: log.dateTime, summary, amount });
// DEBUG: Log the final display values
console.log('🎯 Display Summary:', { summary, efficiency, logId: log.id });
list.push({
id: log.id,
type: 'Fuel Logs',
date: log.dateTime,
summary,
amount,
secondary
});
}
}
return list.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
@@ -212,13 +265,21 @@ export const VehicleDetailMobile: React.FC<VehicleDetailMobileProps> = ({
<List disablePadding>
{filteredRecords.map(rec => (
<ListItem key={rec.id} divider button onClick={() => openEditLog(rec.id, rec.type)}>
<ListItemText
primary={rec.summary || new Date(rec.date).toLocaleString()}
secondary={`${new Date(rec.date).toLocaleString()}${rec.type}`}
/>
<Typography sx={{ ml: 2 }} color="text.primary">
{rec.amount || '—'}
</Typography>
<Box sx={{ flexGrow: 1 }}>
{/* Primary line: MPG/km-L and amount */}
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<Typography variant="body1" color="text.primary">
{rec.summary || 'MPG: —'}
</Typography>
<Typography variant="body1" color="text.primary">
{rec.amount || '—'}
</Typography>
</Box>
{/* Secondary line: Grade • Date • Type */}
<Typography variant="body2" color="text.secondary" sx={{ mt: 0.25 }}>
{rec.secondary || `${new Date(rec.date).toLocaleDateString()}${rec.type}`}
</Typography>
</Box>
</ListItem>
))}
</List>