chore: restructure Fuel Logs to list-first with add dialog (refs #168)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Eric Gullickson
2026-02-13 19:49:46 -06:00
parent f2b20aab1a
commit e4be744643
2 changed files with 80 additions and 30 deletions

View File

@@ -0,0 +1,44 @@
/**
* @ai-summary Dialog wrapper for FuelLogForm to create new fuel logs
*/
import React from 'react';
import { Dialog, DialogTitle, DialogContent, IconButton, useMediaQuery } from '@mui/material';
import CloseIcon from '@mui/icons-material/Close';
import { FuelLogForm } from './FuelLogForm';
interface AddFuelLogDialogProps {
open: boolean;
onClose: () => void;
}
export const AddFuelLogDialog: React.FC<AddFuelLogDialogProps> = ({ open, onClose }) => {
const isSmallScreen = useMediaQuery('(max-width:600px)');
return (
<Dialog
open={open}
onClose={onClose}
maxWidth="sm"
fullWidth
fullScreen={isSmallScreen}
PaperProps={{
sx: { maxHeight: isSmallScreen ? '100%' : '90vh' },
}}
>
<DialogTitle sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
Log Fuel
<IconButton
aria-label="close"
onClick={onClose}
sx={{ minWidth: 44, minHeight: 44 }}
>
<CloseIcon />
</IconButton>
</DialogTitle>
<DialogContent sx={{ p: { xs: 1, sm: 2 } }}>
<FuelLogForm onSuccess={onClose} />
</DialogContent>
</Dialog>
);
};

View File

@@ -1,12 +1,12 @@
import React, { useState } from 'react';
import { Grid, Typography, Box } from '@mui/material';
import { Typography, Box, Button as MuiButton } from '@mui/material';
import AddIcon from '@mui/icons-material/Add';
import { useQueryClient } from '@tanstack/react-query';
import { FuelLogForm } from '../components/FuelLogForm';
import { FuelLogsList } from '../components/FuelLogsList';
import { FuelLogEditDialog } from '../components/FuelLogEditDialog';
import { AddFuelLogDialog } from '../components/AddFuelLogDialog';
import { useFuelLogs } from '../hooks/useFuelLogs';
import { FuelStatsCard } from '../components/FuelStatsCard';
import { FormSuspense } from '../../../components/SuspenseWrappers';
import { FuelLogResponse, UpdateFuelLogRequest } from '../types/fuel-logs.types';
import { fuelLogsApi } from '../api/fuel-logs.api';
@@ -14,9 +14,7 @@ export const FuelLogsPage: React.FC = () => {
const { fuelLogs, isLoading, error } = useFuelLogs();
const queryClient = useQueryClient();
const [editingLog, setEditingLog] = useState<FuelLogResponse | null>(null);
// DEBUG: Log page renders
console.log('[FuelLogsPage] Render - fuel logs count:', fuelLogs?.length, 'isLoading:', isLoading, 'error:', !!error);
const [showAddDialog, setShowAddDialog] = useState(false);
const handleEdit = (log: FuelLogResponse) => {
setEditingLog(log);
@@ -24,9 +22,6 @@ export const FuelLogsPage: React.FC = () => {
const handleDelete = async (_logId: string) => {
try {
console.log('[FuelLogsPage] handleDelete called - using targeted query updates');
// Use targeted invalidation instead of broad invalidation
// This prevents unnecessary re-renders of the form
queryClient.refetchQueries({ queryKey: ['fuelLogs', 'all'] });
} catch (error) {
console.error('Failed to refresh fuel logs after delete:', error);
@@ -35,15 +30,12 @@ export const FuelLogsPage: React.FC = () => {
const handleSaveEdit = async (id: string, data: UpdateFuelLogRequest) => {
try {
console.log('[FuelLogsPage] handleSaveEdit called - using targeted query updates');
await fuelLogsApi.update(id, data);
// Use targeted refetch instead of broad invalidation
// This prevents unnecessary re-renders of the form
queryClient.refetchQueries({ queryKey: ['fuelLogs', 'all'] });
setEditingLog(null);
} catch (error) {
console.error('Failed to update fuel log:', error);
throw error; // Re-throw to let the dialog handle the error
throw error;
}
};
@@ -78,22 +70,36 @@ export const FuelLogsPage: React.FC = () => {
}
return (
<FormSuspense>
<Grid container spacing={2}>
<Grid item xs={12} md={6}>
<FuelLogForm />
</Grid>
<Grid item xs={12} md={6}>
<Typography variant="h6" gutterBottom>Summary</Typography>
<FuelStatsCard logs={fuelLogs} />
<Typography variant="h6" sx={{ mt: 3 }} gutterBottom>Recent Fuel Logs</Typography>
<FuelLogsList
logs={fuelLogs}
onEdit={handleEdit}
onDelete={handleDelete}
/>
</Grid>
</Grid>
<Box>
{/* Header with Add button */}
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}>
<Typography variant="h5" sx={{ fontWeight: 600 }}>Fuel Logs</Typography>
<MuiButton
variant="contained"
startIcon={<AddIcon />}
onClick={() => setShowAddDialog(true)}
>
Add Fuel Log
</MuiButton>
</Box>
{/* Summary Stats */}
<Box sx={{ mb: 3 }}>
<FuelStatsCard logs={fuelLogs} />
</Box>
{/* Fuel Logs List */}
<FuelLogsList
logs={fuelLogs}
onEdit={handleEdit}
onDelete={handleDelete}
/>
{/* Add Dialog */}
<AddFuelLogDialog
open={showAddDialog}
onClose={() => setShowAddDialog(false)}
/>
{/* Edit Dialog */}
<FuelLogEditDialog
@@ -102,6 +108,6 @@ export const FuelLogsPage: React.FC = () => {
onClose={handleCloseEdit}
onSave={handleSaveEdit}
/>
</FormSuspense>
</Box>
);
};