fix: edit buttons
All checks were successful
Deploy to Staging / Build Images (push) Successful in 2m33s
Deploy to Staging / Deploy to Staging (push) Successful in 36s
Deploy to Staging / Verify Staging (push) Successful in 6s
Deploy to Staging / Notify Staging Ready (push) Successful in 5s
Deploy to Staging / Notify Staging Failure (push) Has been skipped
All checks were successful
Deploy to Staging / Build Images (push) Successful in 2m33s
Deploy to Staging / Deploy to Staging (push) Successful in 36s
Deploy to Staging / Verify Staging (push) Successful in 6s
Deploy to Staging / Notify Staging Ready (push) Successful in 5s
Deploy to Staging / Notify Staging Failure (push) Has been skipped
This commit is contained in:
10
docs/E2E-TESTING.md
Normal file
10
docs/E2E-TESTING.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Test scenarios to verify:
|
||||||
|
|
||||||
|
| Test | Year | VIN | License Plate | Expected |
|
||||||
|
|-------------------------|------|--------------------|---------------|---------------------------|
|
||||||
|
| 1. Edit bug fix | Any | null (existing) | "TEST-123" | Should save without error |
|
||||||
|
| 2. Modern + VIN only | 2020 | Valid 17-char | Empty | Should work |
|
||||||
|
| 3. Modern + plate only | 2020 | Empty | "ABC-123" | Should work |
|
||||||
|
| 4. Modern + neither | 2020 | Empty | Empty | Should fail validation |
|
||||||
|
| 5. Pre-1981 + neither | 1970 | Empty | Empty | Should work |
|
||||||
|
| 6. Pre-1981 + short VIN | 1965 | "ABC123" (6 chars) | Empty | Should work |
|
||||||
@@ -30,10 +30,8 @@ You are a senior software engineer specializsing in NodeJS, Typescript, front en
|
|||||||
*** CHANGES TO IMPLEMENT ***
|
*** CHANGES TO IMPLEMENT ***
|
||||||
- Research this code base and ask iterative questions to compile a complete plan.
|
- Research this code base and ask iterative questions to compile a complete plan.
|
||||||
- We will pair troubleshoot this. Tell me what logs and things to run and I will
|
- We will pair troubleshoot this. Tell me what logs and things to run and I will
|
||||||
- There is a bug in the ability to add and edit vehicles
|
- There is a bug in the vehicles screen
|
||||||
- Change it so the every vehicle older than 1981 does not have a 17 digit VIN requirement.
|
- The pencil icon on the vehicle cards does not take you to the edit screen. It does nothing.
|
||||||
- Verify the edit logic. When I had a license plate but no VIN, it still said the VIN was required.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -265,6 +265,50 @@ const AddVehicleScreen: React.FC<AddVehicleScreenProps> = ({ onBack, onAdded })
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface EditVehicleScreenProps {
|
||||||
|
vehicle: Vehicle;
|
||||||
|
onBack: () => void;
|
||||||
|
onUpdated: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EditVehicleScreen: React.FC<EditVehicleScreenProps> = ({ vehicle, onBack, onUpdated }) => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
const handleUpdateVehicle = async (data: CreateVehicleRequest) => {
|
||||||
|
try {
|
||||||
|
const { vehiclesApi } = await import('./features/vehicles/api/vehicles.api');
|
||||||
|
await vehiclesApi.update(vehicle.id, data);
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['vehicles'] });
|
||||||
|
onUpdated();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to update vehicle:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<GlassCard>
|
||||||
|
<div className="p-4">
|
||||||
|
<div className="flex items-center justify-between mb-4">
|
||||||
|
<h2 className="text-lg font-semibold text-slate-800">Edit Vehicle</h2>
|
||||||
|
<button
|
||||||
|
onClick={onBack}
|
||||||
|
className="p-2 hover:bg-gray-100 rounded-full transition-colors"
|
||||||
|
>
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<VehicleForm
|
||||||
|
initialData={vehicle}
|
||||||
|
onSubmit={handleUpdateVehicle}
|
||||||
|
onCancel={onBack}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</GlassCard>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const { isLoading, isAuthenticated, user } = useAuth0();
|
const { isLoading, isAuthenticated, user } = useAuth0();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
@@ -440,6 +484,16 @@ function App() {
|
|||||||
navigateToVehicleSubScreen('list', undefined, { source: 'vehicle-added' });
|
navigateToVehicleSubScreen('list', undefined, { source: 'vehicle-added' });
|
||||||
}, [navigateToVehicleSubScreen]);
|
}, [navigateToVehicleSubScreen]);
|
||||||
|
|
||||||
|
const handleEditVehicle = useCallback(() => {
|
||||||
|
if (selectedVehicle) {
|
||||||
|
navigateToVehicleSubScreen('edit', selectedVehicle.id, { source: 'vehicle-detail' });
|
||||||
|
}
|
||||||
|
}, [navigateToVehicleSubScreen, selectedVehicle]);
|
||||||
|
|
||||||
|
const handleVehicleUpdated = useCallback(() => {
|
||||||
|
navigateToVehicleSubScreen('detail', selectedVehicle?.id, { source: 'vehicle-updated' });
|
||||||
|
}, [navigateToVehicleSubScreen, selectedVehicle]);
|
||||||
|
|
||||||
// Enhanced debug component
|
// Enhanced debug component
|
||||||
const DebugInfo = () => (
|
const DebugInfo = () => (
|
||||||
<MobileDebugPanel visible={import.meta.env.MODE === 'development'} />
|
<MobileDebugPanel visible={import.meta.env.MODE === 'development'} />
|
||||||
@@ -602,11 +656,18 @@ function App() {
|
|||||||
<MobileErrorBoundary screenName="Vehicles">
|
<MobileErrorBoundary screenName="Vehicles">
|
||||||
{vehicleSubScreen === 'add' || showAddVehicle ? (
|
{vehicleSubScreen === 'add' || showAddVehicle ? (
|
||||||
<AddVehicleScreen onBack={handleBackToList} onAdded={handleVehicleAdded} />
|
<AddVehicleScreen onBack={handleBackToList} onAdded={handleVehicleAdded} />
|
||||||
) : selectedVehicle && (vehicleSubScreen === 'detail') ? (
|
) : selectedVehicle && vehicleSubScreen === 'edit' ? (
|
||||||
|
<EditVehicleScreen
|
||||||
|
vehicle={selectedVehicle}
|
||||||
|
onBack={handleBackToList}
|
||||||
|
onUpdated={handleVehicleUpdated}
|
||||||
|
/>
|
||||||
|
) : selectedVehicle && vehicleSubScreen === 'detail' ? (
|
||||||
<VehicleDetailMobile
|
<VehicleDetailMobile
|
||||||
vehicle={selectedVehicle}
|
vehicle={selectedVehicle}
|
||||||
onBack={handleBackToList}
|
onBack={handleBackToList}
|
||||||
onLogFuel={() => navigateToScreen("Log Fuel")}
|
onLogFuel={() => navigateToScreen("Log Fuel")}
|
||||||
|
onEdit={handleEditVehicle}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<VehiclesMobileScreen
|
<VehiclesMobileScreen
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ interface VehicleDetailMobileProps {
|
|||||||
vehicle: Vehicle;
|
vehicle: Vehicle;
|
||||||
onBack: () => void;
|
onBack: () => void;
|
||||||
onLogFuel?: () => void;
|
onLogFuel?: () => void;
|
||||||
|
onEdit?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Section: React.FC<{ title: string; children: React.ReactNode }> = ({
|
const Section: React.FC<{ title: string; children: React.ReactNode }> = ({
|
||||||
@@ -33,7 +34,8 @@ const Section: React.FC<{ title: string; children: React.ReactNode }> = ({
|
|||||||
export const VehicleDetailMobile: React.FC<VehicleDetailMobileProps> = ({
|
export const VehicleDetailMobile: React.FC<VehicleDetailMobileProps> = ({
|
||||||
vehicle,
|
vehicle,
|
||||||
onBack,
|
onBack,
|
||||||
onLogFuel
|
onLogFuel,
|
||||||
|
onEdit
|
||||||
}) => {
|
}) => {
|
||||||
const displayName = vehicle.nickname ||
|
const displayName = vehicle.nickname ||
|
||||||
[vehicle.year, vehicle.make, vehicle.model, vehicle.trimLevel].filter(Boolean).join(' ') || 'Vehicle';
|
[vehicle.year, vehicle.make, vehicle.model, vehicle.trimLevel].filter(Boolean).join(' ') || 'Vehicle';
|
||||||
@@ -168,9 +170,15 @@ export const VehicleDetailMobile: React.FC<VehicleDetailMobileProps> = ({
|
|||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box sx={{ display: 'flex', gap: 1.5, mb: 3 }}>
|
<Box sx={{ display: 'flex', gap: 1.5, mb: 3, flexWrap: 'wrap' }}>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
|
onClick={onEdit}
|
||||||
|
>
|
||||||
|
Edit Vehicle
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
onClick={onLogFuel}
|
onClick={onLogFuel}
|
||||||
>
|
>
|
||||||
Add Fuel
|
Add Fuel
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useMemo, useState, useEffect } from 'react';
|
import React, { useMemo, useState, useEffect } from 'react';
|
||||||
import { useParams, useNavigate } from 'react-router-dom';
|
import { useParams, useNavigate, useSearchParams } from 'react-router-dom';
|
||||||
import { Box, Typography, Button as MuiButton, Divider, FormControl, InputLabel, Select, MenuItem, Table, TableHead, TableRow, TableCell, TableBody, Dialog, DialogTitle, DialogContent, useMediaQuery } from '@mui/material';
|
import { Box, Typography, Button as MuiButton, Divider, FormControl, InputLabel, Select, MenuItem, Table, TableHead, TableRow, TableCell, TableBody, Dialog, DialogTitle, DialogContent, useMediaQuery } from '@mui/material';
|
||||||
import { useQueryClient } from '@tanstack/react-query';
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||||
@@ -43,9 +43,10 @@ const DetailField: React.FC<{
|
|||||||
export const VehicleDetailPage: React.FC = () => {
|
export const VehicleDetailPage: React.FC = () => {
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
const [vehicle, setVehicle] = useState<Vehicle | null>(null);
|
const [vehicle, setVehicle] = useState<Vehicle | null>(null);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [isEditing, setIsEditing] = useState(false);
|
const [isEditing, setIsEditing] = useState(() => searchParams.get('edit') === 'true');
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [recordFilter, setRecordFilter] = useState<'All' | 'Fuel Logs' | 'Maintenance' | 'Documents'>('All');
|
const [recordFilter, setRecordFilter] = useState<'All' | 'Fuel Logs' | 'Maintenance' | 'Documents'>('All');
|
||||||
|
|
||||||
@@ -139,11 +140,16 @@ export const VehicleDetailPage: React.FC = () => {
|
|||||||
|
|
||||||
const handleUpdateVehicle = async (data: any) => {
|
const handleUpdateVehicle = async (data: any) => {
|
||||||
if (!vehicle) return;
|
if (!vehicle) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const updatedVehicle = await vehiclesApi.update(vehicle.id, data);
|
const updatedVehicle = await vehiclesApi.update(vehicle.id, data);
|
||||||
setVehicle(updatedVehicle);
|
setVehicle(updatedVehicle);
|
||||||
setIsEditing(false);
|
setIsEditing(false);
|
||||||
|
// Clear the edit query param from URL
|
||||||
|
if (searchParams.has('edit')) {
|
||||||
|
searchParams.delete('edit');
|
||||||
|
setSearchParams(searchParams, { replace: true });
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error updating vehicle:', err);
|
console.error('Error updating vehicle:', err);
|
||||||
}
|
}
|
||||||
@@ -151,6 +157,11 @@ export const VehicleDetailPage: React.FC = () => {
|
|||||||
|
|
||||||
const handleCancelEdit = () => {
|
const handleCancelEdit = () => {
|
||||||
setIsEditing(false);
|
setIsEditing(false);
|
||||||
|
// Clear the edit query param from URL
|
||||||
|
if (searchParams.has('edit')) {
|
||||||
|
searchParams.delete('edit');
|
||||||
|
setSearchParams(searchParams, { replace: true });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ export const VehiclesPage: React.FC = () => {
|
|||||||
<Grid item xs={12} md={6} lg={4} key={vehicle.id}>
|
<Grid item xs={12} md={6} lg={4} key={vehicle.id}>
|
||||||
<VehicleCard
|
<VehicleCard
|
||||||
vehicle={vehicle}
|
vehicle={vehicle}
|
||||||
onEdit={(v) => console.log('Edit', v)}
|
onEdit={(v) => navigate(`/garage/vehicles/${v.id}?edit=true`)}
|
||||||
onDelete={handleDelete}
|
onDelete={handleDelete}
|
||||||
onSelect={handleSelectVehicle}
|
onSelect={handleSelectVehicle}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user