fix: wire up Add Maintenance button on vehicle detail page (refs #194)
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 3m24s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 52s
Deploy to Staging / Verify Staging (pull_request) Successful in 8s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 7s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped

Rename "Schedule Maintenance" to "Add Maintenance", match contained
button style to "Add Fuel Log", and open inline MaintenanceRecordForm
dialog on click. Applied to both desktop and mobile views.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Eric Gullickson
2026-02-15 10:01:33 -06:00
parent 8d6434f166
commit 7140c7e8d4
3 changed files with 69 additions and 7 deletions

View File

@@ -65,9 +65,10 @@ type FormData = z.infer<typeof schema>;
interface MaintenanceRecordFormProps {
vehicleId?: string;
onSuccess?: () => void;
}
export const MaintenanceRecordForm: React.FC<MaintenanceRecordFormProps> = ({ vehicleId }) => {
export const MaintenanceRecordForm: React.FC<MaintenanceRecordFormProps> = ({ vehicleId, onSuccess }) => {
const { data: vehicles, isLoading: isLoadingVehicles } = useVehicles();
const { createRecord, isRecordMutating } = useMaintenanceRecords();
const [selectedCategory, setSelectedCategory] = useState<MaintenanceCategory | null>(null);
@@ -211,6 +212,7 @@ export const MaintenanceRecordForm: React.FC<MaintenanceRecordFormProps> = ({ ve
await createRecord(payload);
toast.success('Maintenance record added successfully');
onSuccess?.();
// Reset form
reset({

View File

@@ -3,13 +3,14 @@
*/
import React, { useMemo, useState } from 'react';
import { Box, Typography, Button, Card, CardContent, Divider, FormControl, InputLabel, Select, MenuItem, List, ListItem, ListItemButton } from '@mui/material';
import { Box, Typography, Button, Card, CardContent, Divider, FormControl, InputLabel, Select, MenuItem, List, ListItem, ListItemButton, Dialog, DialogTitle, DialogContent } from '@mui/material';
import { useQueryClient } from '@tanstack/react-query';
import { Vehicle } from '../types/vehicles.types';
import { useFuelLogs } from '../../fuel-logs/hooks/useFuelLogs';
import { FuelLogResponse, UpdateFuelLogRequest } from '../../fuel-logs/types/fuel-logs.types';
import { FuelLogEditDialog } from '../../fuel-logs/components/FuelLogEditDialog';
import { fuelLogsApi } from '../../fuel-logs/api/fuel-logs.api';
import { MaintenanceRecordForm } from '../../maintenance/components/MaintenanceRecordForm';
import { VehicleImage } from '../components/VehicleImage';
import { OwnershipCostsList } from '../../ownership-costs';
import { getVehicleLabel } from '@/core/utils/vehicleDisplay';
@@ -46,6 +47,7 @@ export const VehicleDetailMobile: React.FC<VehicleDetailMobileProps> = ({
const { fuelLogs, isLoading: isFuelLoading } = useFuelLogs(vehicle.id);
const queryClient = useQueryClient();
const [editingLog, setEditingLog] = useState<FuelLogResponse | null>(null);
const [showMaintenanceDialog, setShowMaintenanceDialog] = useState(false);
// Unit conversions are now handled by the backend
type VehicleRecord = {
@@ -184,8 +186,11 @@ export const VehicleDetailMobile: React.FC<VehicleDetailMobileProps> = ({
>
Add Fuel
</Button>
<Button variant="outlined">
Maintenance
<Button
variant="outlined"
onClick={() => setShowMaintenanceDialog(true)}
>
Add Maintenance
</Button>
</Box>
@@ -300,6 +305,32 @@ export const VehicleDetailMobile: React.FC<VehicleDetailMobileProps> = ({
onClose={handleCloseEdit}
onSave={handleSaveEdit}
/>
{/* Add Maintenance Dialog */}
<Dialog
open={showMaintenanceDialog}
onClose={() => setShowMaintenanceDialog(false)}
maxWidth="md"
fullWidth
fullScreen
PaperProps={{
sx: { maxHeight: '90vh' }
}}
>
<DialogTitle>Add Maintenance</DialogTitle>
<DialogContent>
<Box sx={{ mt: 1 }}>
<MaintenanceRecordForm
vehicleId={vehicle.id}
onSuccess={() => {
setShowMaintenanceDialog(false);
queryClient.invalidateQueries({ queryKey: ['maintenanceRecords', vehicle.id] });
queryClient.invalidateQueries({ queryKey: ['maintenanceRecords'] });
}}
/>
</Box>
</DialogContent>
</Dialog>
</Box>
);
};

View File

@@ -21,6 +21,7 @@ import { useFuelLogs } from '../../fuel-logs/hooks/useFuelLogs';
import { FuelLogResponse, UpdateFuelLogRequest } from '../../fuel-logs/types/fuel-logs.types';
import { FuelLogEditDialog } from '../../fuel-logs/components/FuelLogEditDialog';
import { FuelLogForm } from '../../fuel-logs/components/FuelLogForm';
import { MaintenanceRecordForm } from '../../maintenance/components/MaintenanceRecordForm';
// Unit conversions now handled by backend
import { fuelLogsApi } from '../../fuel-logs/api/fuel-logs.api';
import { OwnershipCostsList } from '../../ownership-costs';
@@ -63,6 +64,7 @@ export const VehicleDetailPage: React.FC = () => {
const queryClient = useQueryClient();
const [editingLog, setEditingLog] = useState<FuelLogResponse | null>(null);
const [showAddDialog, setShowAddDialog] = useState(false);
const [showMaintenanceDialog, setShowMaintenanceDialog] = useState(false);
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [documentToDelete, setDocumentToDelete] = useState<DocumentRecord | null>(null);
const isSmallScreen = useMediaQuery('(max-width:600px)');
@@ -355,11 +357,12 @@ export const VehicleDetailPage: React.FC = () => {
Add Fuel Log
</MuiButton>
<MuiButton
variant="outlined"
variant="contained"
startIcon={<BuildIcon />}
sx={{ borderRadius: '999px' }}
onClick={() => setShowMaintenanceDialog(true)}
>
Schedule Maintenance
Add Maintenance
</MuiButton>
</Box>
@@ -545,6 +548,32 @@ export const VehicleDetailPage: React.FC = () => {
</DialogContent>
</Dialog>
{/* Add Maintenance Dialog */}
<Dialog
open={showMaintenanceDialog}
onClose={() => setShowMaintenanceDialog(false)}
maxWidth="md"
fullWidth
fullScreen={isSmallScreen}
PaperProps={{
sx: { maxHeight: '90vh' }
}}
>
<DialogTitle>Add Maintenance</DialogTitle>
<DialogContent>
<Box sx={{ mt: 1 }}>
<MaintenanceRecordForm
vehicleId={vehicle?.id}
onSuccess={() => {
setShowMaintenanceDialog(false);
queryClient.invalidateQueries({ queryKey: ['maintenanceRecords', vehicle?.id] });
queryClient.invalidateQueries({ queryKey: ['maintenanceRecords'] });
}}
/>
</Box>
</DialogContent>
</Dialog>
{/* Delete Document Confirmation Dialog */}
<DeleteDocumentConfirmDialog
open={deleteDialogOpen}