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

@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useMemo, useState } from 'react';
import {
Card,
CardContent,
@@ -20,6 +20,7 @@ import {
import { Edit, Delete } from '@mui/icons-material';
import { FuelLogResponse } from '../types/fuel-logs.types';
import { fuelLogsApi } from '../api/fuel-logs.api';
import { useUnits } from '../../../core/units/UnitsContext';
interface FuelLogsListProps {
logs?: FuelLogResponse[];
@@ -30,10 +31,26 @@ interface FuelLogsListProps {
export const FuelLogsList: React.FC<FuelLogsListProps> = ({ logs, onEdit, onDelete }) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const { unitSystem, convertDistance, convertVolume } = useUnits();
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [logToDelete, setLogToDelete] = useState<FuelLogResponse | null>(null);
const [isDeleting, setIsDeleting] = useState(false);
// Precompute previous odometer per log for delta calculations
const prevOdoById = useMemo(() => {
const map = new Map<string, number | undefined>();
if (!Array.isArray(logs)) return map;
const asc = [...logs].sort((a, b) => new Date(a.dateTime).getTime() - new Date(b.dateTime).getTime());
let lastOdo: number | undefined = undefined;
for (const l of asc) {
map.set(l.id, lastOdo);
if (typeof l.odometerReading === 'number' && !isNaN(l.odometerReading)) {
lastOdo = l.odometerReading;
}
}
return map;
}, [logs]);
const handleDeleteClick = (log: FuelLogResponse) => {
setLogToDelete(log);
setDeleteDialogOpen(true);
@@ -110,6 +127,31 @@ export const FuelLogsList: React.FC<FuelLogsListProps> = ({ logs, onEdit, onDele
? `Trip: ${log.tripDistance}`
: 'No distance';
// Compute local efficiency if not provided
let localEffLabel: string | null = null;
try {
const gallons = typeof log.fuelUnits === 'number' ? log.fuelUnits : undefined;
let miles: number | undefined =
typeof log.tripDistance === 'number' && !isNaN(log.tripDistance)
? log.tripDistance
: undefined;
if (miles === undefined && typeof log.odometerReading === 'number') {
const prev = prevOdoById.get(log.id);
if (typeof prev === 'number' && log.odometerReading > prev) {
miles = log.odometerReading - prev;
}
}
if (typeof miles === 'number' && typeof gallons === 'number' && gallons > 0) {
if (unitSystem === 'metric') {
const km = convertDistance(miles);
const liters = convertVolume(gallons);
if (liters > 0) localEffLabel = `${(km / liters).toFixed(1)} km/L`;
} else {
localEffLabel = `${(miles / gallons).toFixed(1)} MPG`;
}
}
} catch {}
return (
<ListItem
key={log.id}
@@ -133,18 +175,19 @@ export const FuelLogsList: React.FC<FuelLogsListProps> = ({ logs, onEdit, onDele
secondary={`${fuelUnits} @ $${costPerUnit}${distanceText}`}
sx={{ flex: 1, minWidth: 0 }}
/>
{log.efficiency &&
typeof log.efficiency === 'number' &&
!isNaN(log.efficiency) &&
log.efficiencyLabel && (
{(log.efficiency && typeof log.efficiency === 'number' && !isNaN(log.efficiency) && log.efficiencyLabel) || localEffLabel ? (
<Box sx={{ mr: isMobile ? 0 : 1 }}>
<Chip
label={`${log.efficiency.toFixed(1)} ${log.efficiencyLabel}`}
label={
log.efficiency && log.efficiencyLabel
? `${log.efficiency.toFixed(1)} ${log.efficiencyLabel}`
: localEffLabel || ''
}
size="small"
color="primary"
/>
</Box>
)}
) : null}
</Box>
<Box sx={{
@@ -238,4 +281,3 @@ export const FuelLogsList: React.FC<FuelLogsListProps> = ({ logs, onEdit, onDele
</>
);
};