fix: Wire up Add Maintenance button on vehicle detail page (#194) #195

Merged
egullickson merged 1 commits from issue-194-fix-add-maintenance-button into main 2026-02-15 16:09:53 +00:00
3 changed files with 69 additions and 7 deletions

View File

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

View File

@@ -3,13 +3,14 @@
*/ */
import React, { useMemo, useState } from 'react'; 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 { useQueryClient } from '@tanstack/react-query';
import { Vehicle } from '../types/vehicles.types'; import { Vehicle } from '../types/vehicles.types';
import { useFuelLogs } from '../../fuel-logs/hooks/useFuelLogs'; import { useFuelLogs } from '../../fuel-logs/hooks/useFuelLogs';
import { FuelLogResponse, UpdateFuelLogRequest } from '../../fuel-logs/types/fuel-logs.types'; import { FuelLogResponse, UpdateFuelLogRequest } from '../../fuel-logs/types/fuel-logs.types';
import { FuelLogEditDialog } from '../../fuel-logs/components/FuelLogEditDialog'; import { FuelLogEditDialog } from '../../fuel-logs/components/FuelLogEditDialog';
import { fuelLogsApi } from '../../fuel-logs/api/fuel-logs.api'; import { fuelLogsApi } from '../../fuel-logs/api/fuel-logs.api';
import { MaintenanceRecordForm } from '../../maintenance/components/MaintenanceRecordForm';
import { VehicleImage } from '../components/VehicleImage'; import { VehicleImage } from '../components/VehicleImage';
import { OwnershipCostsList } from '../../ownership-costs'; import { OwnershipCostsList } from '../../ownership-costs';
import { getVehicleLabel } from '@/core/utils/vehicleDisplay'; import { getVehicleLabel } from '@/core/utils/vehicleDisplay';
@@ -46,6 +47,7 @@ export const VehicleDetailMobile: React.FC<VehicleDetailMobileProps> = ({
const { fuelLogs, isLoading: isFuelLoading } = useFuelLogs(vehicle.id); const { fuelLogs, isLoading: isFuelLoading } = useFuelLogs(vehicle.id);
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const [editingLog, setEditingLog] = useState<FuelLogResponse | null>(null); const [editingLog, setEditingLog] = useState<FuelLogResponse | null>(null);
const [showMaintenanceDialog, setShowMaintenanceDialog] = useState(false);
// Unit conversions are now handled by the backend // Unit conversions are now handled by the backend
type VehicleRecord = { type VehicleRecord = {
@@ -184,8 +186,11 @@ export const VehicleDetailMobile: React.FC<VehicleDetailMobileProps> = ({
> >
Add Fuel Add Fuel
</Button> </Button>
<Button variant="outlined"> <Button
Maintenance variant="outlined"
onClick={() => setShowMaintenanceDialog(true)}
>
Add Maintenance
</Button> </Button>
</Box> </Box>
@@ -300,6 +305,32 @@ export const VehicleDetailMobile: React.FC<VehicleDetailMobileProps> = ({
onClose={handleCloseEdit} onClose={handleCloseEdit}
onSave={handleSaveEdit} 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> </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 { FuelLogResponse, UpdateFuelLogRequest } from '../../fuel-logs/types/fuel-logs.types';
import { FuelLogEditDialog } from '../../fuel-logs/components/FuelLogEditDialog'; import { FuelLogEditDialog } from '../../fuel-logs/components/FuelLogEditDialog';
import { FuelLogForm } from '../../fuel-logs/components/FuelLogForm'; import { FuelLogForm } from '../../fuel-logs/components/FuelLogForm';
import { MaintenanceRecordForm } from '../../maintenance/components/MaintenanceRecordForm';
// Unit conversions now handled by backend // Unit conversions now handled by backend
import { fuelLogsApi } from '../../fuel-logs/api/fuel-logs.api'; import { fuelLogsApi } from '../../fuel-logs/api/fuel-logs.api';
import { OwnershipCostsList } from '../../ownership-costs'; import { OwnershipCostsList } from '../../ownership-costs';
@@ -63,6 +64,7 @@ export const VehicleDetailPage: React.FC = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const [editingLog, setEditingLog] = useState<FuelLogResponse | null>(null); const [editingLog, setEditingLog] = useState<FuelLogResponse | null>(null);
const [showAddDialog, setShowAddDialog] = useState(false); const [showAddDialog, setShowAddDialog] = useState(false);
const [showMaintenanceDialog, setShowMaintenanceDialog] = useState(false);
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [documentToDelete, setDocumentToDelete] = useState<DocumentRecord | null>(null); const [documentToDelete, setDocumentToDelete] = useState<DocumentRecord | null>(null);
const isSmallScreen = useMediaQuery('(max-width:600px)'); const isSmallScreen = useMediaQuery('(max-width:600px)');
@@ -355,11 +357,12 @@ export const VehicleDetailPage: React.FC = () => {
Add Fuel Log Add Fuel Log
</MuiButton> </MuiButton>
<MuiButton <MuiButton
variant="outlined" variant="contained"
startIcon={<BuildIcon />} startIcon={<BuildIcon />}
sx={{ borderRadius: '999px' }} sx={{ borderRadius: '999px' }}
onClick={() => setShowMaintenanceDialog(true)}
> >
Schedule Maintenance Add Maintenance
</MuiButton> </MuiButton>
</Box> </Box>
@@ -545,6 +548,32 @@ export const VehicleDetailPage: React.FC = () => {
</DialogContent> </DialogContent>
</Dialog> </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 */} {/* Delete Document Confirmation Dialog */}
<DeleteDocumentConfirmDialog <DeleteDocumentConfirmDialog
open={deleteDialogOpen} open={deleteDialogOpen}