feat: implement vehicle management features including add, edit, and …#7
Conversation
docs: Add build status badges for all services in README.md for impro…
…delete vehicle functionality
WalkthroughThis PR adds a complete vehicle management frontend for a Next.js 14 TypeScript application. It introduces new React components for vehicle creation and editing, a vehicles list page with full CRUD operations, a vehicle details page with photo upload and service history display, and a vehicleService API client. The customer dashboard is refactored from content-heavy placeholders to a navigation-focused card layout. A Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant VehiclesPage as Vehicles Page
participant Modal as Modal Form
participant VehicleService as Vehicle Service
participant API as Backend API
User->>VehiclesPage: Load /dashboard/vehicles
VehiclesPage->>VehicleService: getMyVehicles()
VehicleService->>API: GET /vehicles
API-->>VehicleService: VehicleListItem[]
VehicleService-->>VehiclesPage: vehicles
VehiclesPage->>VehiclesPage: Render grid of VehicleCard
User->>VehiclesPage: Click "Add New Vehicle"
VehiclesPage->>Modal: Open AddVehicleForm
User->>Modal: Fill form, submit
Modal->>VehicleService: registerVehicle(payload)
VehicleService->>API: POST /vehicles
API-->>VehicleService: VehicleResponse
VehicleService-->>Modal: response
Modal->>VehiclesPage: onSuccess callback
VehiclesPage->>VehiclesPage: Refresh vehicle list
User->>VehiclesPage: Click Delete on VehicleCard
User->>User: Confirm delete dialog
VehiclesPage->>VehicleService: deleteVehicle(vehicleId)
VehicleService->>API: DELETE /vehicles/{id}
API-->>VehicleService: VehicleResponse
VehicleService-->>VehiclesPage: response
VehiclesPage->>VehiclesPage: Refresh vehicle list
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…ency and readability
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (6)
.gitattributes (2)
12-12: Remove duplicate Markdown file rule.Lines 12 and 19 both specify
*.md text eol=lf. Keep one and remove the duplicate.Apply this diff to remove the duplicate:
# Markdown *.md text eol=lf # Mark common web files as LF *.json text eol=lf *.css text eol=lf *.scss text eol=lf *.html text eol=lf - *.md text eol=lfAlso applies to: 19-19
1-63: Clarify repository structure and scope rules if this is a monorepo.This
.gitattributesfile defines rules for two separate projects (Frontend_Web and API_Gateway). If this file is at the monorepo root with both projects as subdirectories, the rules should be scoped with path patterns (e.g.,Frontend_Web/**/*.ts) to avoid accidentally applying API_Gateway rules to Frontend_Web files and vice versa. This becomes increasingly important as the projects evolve and potentially add file types not yet covered.Please clarify:
- Is this a monorepo with
Frontend_Web/andAPI_Gateway/as subdirectories?- If yes, should each project's rules be scoped with path patterns?
If this is confirmed to be a monorepo, the rules should be refactored like this:
- # TypeScript / JavaScript - *.ts text eol=lf + # Frontend_Web (Next.js / TypeScript project) + Frontend_Web/**/*.ts text eol=lf + Frontend_Web/**/*.tsx text eol=lf + Frontend_Web/**/*.js text eol=lf + Frontend_Web/**/*.jsx text eol=lf ... - # Go - *.go text eol=lf + # API_Gateway (Go project) + API_Gateway/**/*.go text eol=lf + API_Gateway/**/*.mod text eol=lf + API_Gateway/**/*.sum text eol=lfAlternatively, if each project should have its own
.gitattributesfile at its root, move the Frontend_Web rules toFrontend_Web/.gitattributesand API_Gateway rules toAPI_Gateway/.gitattributes.src/app/components/VehicleCard.tsx (1)
48-57: Consider replacingconfirm()with a modal dialog.The native
confirm()dialog blocks the UI and lacks styling consistency. For better UX, consider using a custom modal component that matches your design system.src/app/dashboard/vehicles/page.tsx (1)
38-38: Replacealert()with a toast notification or error modal.The
alert()dialog blocks the UI and provides poor UX. Consider using a toast library (like react-hot-toast or sonner) or displaying error messages inline.src/app/dashboard/vehicles/[vehicleId]/page.tsx (2)
103-107: Use Next.js<Image>component for optimization.Standard
<img>tags bypass Next.js automatic image optimization, resulting in slower LCP and higher bandwidth. Replace withnext/imagefor automatic optimization, lazy loading, and responsive sizing.Apply this diff:
+import Image from 'next/image'; // In the component: -<img +<Image src={vehicle.photos[0] as unknown as string} alt={`${vehicle.make} ${vehicle.model}`} - className="w-full h-72 object-cover" + width={800} + height={288} + className="w-full h-72 object-cover" /> // For thumbnails: -<img src={p as unknown as string} alt={`photo-${i}`} className="w-full h-full object-cover" /> +<Image src={p as unknown as string} alt={`photo-${i}`} width={96} height={64} className="w-full h-full object-cover" />Also applies to: 120-120
53-53: Replacealert()with toast notifications.Using
alert()blocks the UI and provides poor UX. Consider using a toast notification library like react-hot-toast or sonner for non-blocking feedback.Also applies to: 55-55
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
.gitattributes(1 hunks)VEHICLE_MANAGEMENT_FRONTEND.md(1 hunks)src/app/components/AddVehicleForm.tsx(1 hunks)src/app/components/EditVehicleForm.tsx(1 hunks)src/app/components/VehicleCard.tsx(1 hunks)src/app/components/dashboards/CustomerDashboard.tsx(3 hunks)src/app/dashboard/vehicles/[vehicleId]/page.tsx(1 hunks)src/app/dashboard/vehicles/page.tsx(1 hunks)src/services/vehicleService.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
src/app/dashboard/vehicles/[vehicleId]/page.tsx (1)
src/services/vehicleService.ts (1)
vehicleService(13-84)
src/services/vehicleService.ts (1)
src/app/dashboard/vehicles/[vehicleId]/page.tsx (7)
VehicleRequest(238-246)VehicleResponse(254-257)VehicleListItem(228-236)Vehicle(214-226)VehicleUpdateRequest(248-252)PhotoUploadResponse(259-262)ServiceHistory(264-270)
src/app/components/VehicleCard.tsx (1)
src/app/dashboard/vehicles/[vehicleId]/page.tsx (1)
VehicleListItem(228-236)
src/app/components/AddVehicleForm.tsx (2)
src/app/dashboard/vehicles/[vehicleId]/page.tsx (1)
VehicleRequest(238-246)src/services/vehicleService.ts (1)
vehicleService(13-84)
src/app/components/EditVehicleForm.tsx (2)
src/app/dashboard/vehicles/[vehicleId]/page.tsx (1)
VehicleUpdateRequest(248-252)src/services/vehicleService.ts (1)
vehicleService(13-84)
src/app/dashboard/vehicles/page.tsx (5)
src/app/dashboard/vehicles/[vehicleId]/page.tsx (1)
VehicleListItem(228-236)src/services/vehicleService.ts (1)
vehicleService(13-84)src/app/components/AddVehicleForm.tsx (1)
AddVehicleForm(11-174)src/app/components/EditVehicleForm.tsx (1)
EditVehicleForm(17-122)src/app/components/VehicleCard.tsx (1)
VehicleCard(11-61)
🪛 Biome (2.1.2)
src/app/dashboard/vehicles/[vehicleId]/page.tsx
[error] 214-215: Shouldn't redeclare 'Vehicle'. Consider to delete it or rename it.
'Vehicle' is defined here:
(lint/suspicious/noRedeclare)
[error] 264-265: Shouldn't redeclare 'ServiceHistory'. Consider to delete it or rename it.
'ServiceHistory' is defined here:
(lint/suspicious/noRedeclare)
🪛 GitHub Actions: Build and Test Frontend_Web
src/app/components/AddVehicleForm.tsx
[error] 32-32: Unexpected any. Specify a different type. ESLint: @typescript-eslint/no-explicit-any.
🪛 GitHub Check: Install, Lint and Build
src/app/dashboard/vehicles/[vehicleId]/page.tsx
[warning] 120-120:
Using <img> could result in slower LCP and higher bandwidth. Consider using <Image /> from next/image or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element
[warning] 103-103:
Using <img> could result in slower LCP and higher bandwidth. Consider using <Image /> from next/image or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element
[failure] 54-54:
Unexpected any. Specify a different type
[failure] 40-40:
Unexpected any. Specify a different type
[failure] 29-29:
Unexpected any. Specify a different type
[warning] 21-21:
React Hook useEffect has missing dependencies: 'loadServiceHistory' and 'loadVehicleDetails'. Either include them or remove the dependency array
src/app/components/AddVehicleForm.tsx
[failure] 32-32:
Unexpected any. Specify a different type
src/app/components/EditVehicleForm.tsx
[failure] 39-39:
Unexpected any. Specify a different type
src/app/dashboard/vehicles/page.tsx
[failure] 37-37:
Unexpected any. Specify a different type
[failure] 22-22:
Unexpected any. Specify a different type
🪛 LanguageTool
VEHICLE_MANAGEMENT_FRONTEND.md
[style] ~5-~5: Some style guides suggest that commas should set off the year in a month-day-year date.
Context: ...LETE** Date Completed: October 17, 2025 Framework: Next.js 14 with TypeSc...
(MISSING_COMMA_AFTER_YEAR)
🔇 Additional comments (11)
src/app/components/EditVehicleForm.tsx (1)
46-52: LGTM!The
handleChangefunction correctly parses mileage as a number with a safe fallback to 0 for invalid input.src/app/components/VehicleCard.tsx (1)
11-60: LGTM!Clean component structure with proper prop handling and navigation integration.
src/app/components/AddVehicleForm.tsx (2)
98-111: LGTM!VIN validation pattern is correct: 17 characters excluding I, O, and Q as per standard VIN format.
39-45: LGTM!The parseInt fallback to 0 safely handles invalid numeric inputs for year and mileage fields.
src/app/dashboard/vehicles/page.tsx (1)
82-91: LGTM!Modal implementation for add and edit forms is clean and provides good UX with backdrop blur and proper z-index stacking.
Also applies to: 94-109
VEHICLE_MANAGEMENT_FRONTEND.md (1)
1-323: LGTM!Comprehensive documentation covering implementation details, features, usage instructions, and technical stack. Well-structured and helpful for onboarding.
src/app/components/dashboards/CustomerDashboard.tsx (1)
1-152: LGTM!The dashboard refactoring successfully shifts from placeholder content to a clean, navigation-focused layout. The new card-based design with clear CTAs provides better user flow to vehicle management, appointments, and service history.
src/services/vehicleService.ts (2)
3-11: Verify type definitions exist in src/types/vehicle.ts.The import references
../types/vehicle, but based on the PR files, these types appear to be defined insrc/app/dashboard/vehicles/[vehicleId]/page.tsxinstead. Ensure type definitions are properly centralized.This verification is covered by the script in the EditVehicleForm.tsx review above.
13-84: LGTM!Clean API service implementation with proper typing, good documentation, and correct handling of multipart form data for photo uploads.
src/app/dashboard/vehicles/[vehicleId]/page.tsx (2)
18-21: LGTM!The useEffect hook correctly depends on
vehicleId. The static analysis warning about missing dependencies forloadVehicleDetailsandloadServiceHistoryis a false positive since these functions are defined inside the component and don't need to be in the dependency array (they're recreated on each render anyway).
85-210: LGTM!The two-column responsive layout with vehicle details, photo gallery, and service history provides excellent UX. The sticky sidebar and empty states are well-implemented.
| try { | ||
| await vehicleService.registerVehicle(formData); | ||
| onSuccess(); | ||
| } catch (err: any) { |
There was a problem hiding this comment.
Replace any with proper error type.
The pipeline is failing due to this any type. Use unknown and type narrowing for better type safety.
Apply this diff:
- } catch (err: any) {
- setError(err.response?.data?.message || 'Failed to add vehicle');
+ } catch (err: unknown) {
+ const message = err && typeof err === 'object' && 'response' in err
+ ? (err as { response?: { data?: { message?: string } } }).response?.data?.message
+ : undefined;
+ setError(message || 'Failed to add vehicle');📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| } catch (err: any) { | |
| } catch (err: unknown) { | |
| const message = err && typeof err === 'object' && 'response' in err | |
| ? (err as { response?: { data?: { message?: string } } }).response?.data?.message | |
| : undefined; | |
| setError(message || 'Failed to add vehicle'); |
🧰 Tools
🪛 GitHub Actions: Build and Test Frontend_Web
[error] 32-32: Unexpected any. Specify a different type. ESLint: @typescript-eslint/no-explicit-any.
🪛 GitHub Check: Install, Lint and Build
[failure] 32-32:
Unexpected any. Specify a different type
🤖 Prompt for AI Agents
In src/app/components/AddVehicleForm.tsx around line 32, the catch block
currently types the error as "any"; change it to "unknown" and perform
type-narrowing before using the error. Specifically, update the catch parameter
to err: unknown, then inside the block check if (err instanceof Error) to access
err.message (or other Error properties), otherwise handle non-Error values
(e.g., stringify or use a default message) so that logging and downstream
handling are type-safe.
| "use client"; | ||
| import { useState } from 'react'; | ||
| import { vehicleService } from '@/services/vehicleService'; | ||
| import type { VehicleUpdateRequest } from '@/types/vehicle'; |
There was a problem hiding this comment.
🧩 Analysis chain
Verify type import path.
The import references @/types/vehicle, but the relevant code snippets show these types are exported from src/app/dashboard/vehicles/[vehicleId]/page.tsx. Either create a dedicated src/types/vehicle.ts file to centralize type definitions, or update the import path to reference the page file directly.
Run this script to check if the types file exists:
🏁 Script executed:
#!/bin/bash
# Check if src/types/vehicle.ts exists and examine type exports
if [ -f "src/types/vehicle.ts" ]; then
echo "=== src/types/vehicle.ts exists ==="
cat src/types/vehicle.ts
else
echo "=== src/types/vehicle.ts NOT FOUND ==="
echo "Types may need to be extracted to this location"
fi
# Search for VehicleUpdateRequest definition
echo ""
echo "=== All VehicleUpdateRequest definitions ==="
rg -n "interface VehicleUpdateRequest" -A 4Length of output: 446
---
🏁 Script executed:
```shell
#!/bin/bash
# Check usages of @/types/vehicle import path
echo "=== Files importing from @/types/vehicle ==="
rg -n "@/types/vehicle" --type=ts --type=tsx
# Check all VehicleUpdateRequest usages
echo ""
echo "=== All VehicleUpdateRequest usages ==="
rg -n "VehicleUpdateRequest" --type=ts --type=tsx -B2 -A2
# Check EditVehicleForm.tsx imports
echo ""
echo "=== EditVehicleForm.tsx imports ==="
head -20 src/app/components/EditVehicleForm.tsx
Length of output: 276
🏁 Script executed:
#!/bin/bash
# Find EditVehicleForm.tsx file
echo "=== Locating EditVehicleForm.tsx ==="
fd -i "editvehicleform" --type f
echo ""
echo "=== All files with 'vehicle' in name ==="
fd "vehicle" --type f
echo ""
echo "=== Searching for @/types/vehicle import (no type restrictions) ==="
rg "@/types/vehicle" -n
echo ""
echo "=== Searching for VehicleUpdateRequest usage ==="
rg "VehicleUpdateRequest" -n -B1 -A1Length of output: 2272
🏁 Script executed:
#!/bin/bash
# Examine full src/types/vehicle.ts
echo "=== Full src/types/vehicle.ts content ==="
cat src/types/vehicle.ts
echo "(END OF FILE)"
echo ""
echo "=== Check for VehicleUpdateRequest export in src/types/vehicle.ts ==="
rg "VehicleUpdateRequest" src/types/vehicle.ts
echo ""
echo "=== Check if page file exports VehicleUpdateRequest ==="
rg "export.*VehicleUpdateRequest" src/app/dashboard/vehicles/[vehicleId]/page.tsxLength of output: 223
Centralize type definitions in src/types/vehicle.ts.
The file src/types/vehicle.ts is empty, yet multiple files (EditVehicleForm.tsx, vehicleService.ts, and others) import types from it, including VehicleUpdateRequest. The type is currently defined at src/app/dashboard/vehicles/[vehicleId]/page.tsx:248 but not exported from the centralized types file. All type definitions referenced in imports from @/types/vehicle must be moved to or re-exported from src/types/vehicle.ts to resolve the import failures.
🤖 Prompt for AI Agents
In src/app/components/EditVehicleForm.tsx around line 4, the import
VehicleUpdateRequest comes from an empty src/types/vehicle.ts; the actual type
is defined in src/app/dashboard/vehicles/[vehicleId]/page.tsx (around line 248).
Move the VehicleUpdateRequest type (and any other vehicle-related types used
across the codebase) into src/types/vehicle.ts and export them, then update or
keep imports to reference "@/types/vehicle". Alternatively, re-export the type
from src/types/vehicle.ts by importing it from the page.tsx and exporting it
from the central file, and remove any duplicate local type definitions so all
files consistently consume the centralized exported types.
| try { | ||
| await vehicleService.updateVehicle(vehicleId, formData); | ||
| onSuccess(); | ||
| } catch (err: any) { |
There was a problem hiding this comment.
Replace any with proper error type.
Use a typed error interface or unknown with type narrowing to improve type safety.
Apply this diff:
- } catch (err: any) {
+ } catch (err: unknown) {
- setError(err.response?.data?.message || 'Failed to update vehicle');
+ const message = err instanceof Error && 'response' in err
+ ? (err as any).response?.data?.message
+ : 'Failed to update vehicle';
+ setError(message || 'Failed to update vehicle');Or define an API error type:
interface ApiError {
response?: {
data?: {
message?: string;
};
};
}
// Then use:
} catch (err: unknown) {
const apiError = err as ApiError;
setError(apiError.response?.data?.message || 'Failed to update vehicle');
}🧰 Tools
🪛 GitHub Check: Install, Lint and Build
[failure] 39-39:
Unexpected any. Specify a different type
🤖 Prompt for AI Agents
In src/app/components/EditVehicleForm.tsx around line 39, the catch clause
currently types the caught error as `any`; change it to `unknown` and perform
type narrowing or define an ApiError interface (with optional
response.data.message) and cast the caught value to that interface before
accessing message. Specifically, replace `catch (err: any)` with `catch (err:
unknown)` and then either use a type guard to check shape or cast to the
ApiError type and setError using the optional chaining fallback (e.g.,
apiError.response?.data?.message || 'Failed to update vehicle').
| import { useState, useEffect } from 'react'; | ||
| import { useRouter, useParams } from 'next/navigation'; | ||
| import { vehicleService } from '@/services/vehicleService'; | ||
| import type { Vehicle, ServiceHistory } from '@/types/vehicle'; |
There was a problem hiding this comment.
Critical: Type redeclaration causing build errors.
The types are imported from @/types/vehicle at line 5, then redeclared at lines 214-270. This causes the redeclaration errors flagged by Biome. These type definitions should be moved to a centralized src/types/vehicle.ts file and imported, not defined inline in the page component.
Create src/types/vehicle.ts:
export interface Vehicle {
vehicleId: string;
customerId: string;
make: string;
model: string;
year: number;
vin: string;
licensePlate: string;
color?: string;
mileage: number;
photos?: string[]; // Add missing photos property
createdAt: string;
updatedAt: string;
}
export interface VehicleListItem {
vehicleId: string;
make: string;
model: string;
year: number;
licensePlate: string;
color?: string;
mileage: number;
}
export interface VehicleRequest {
make: string;
model: string;
year: number;
vin: string;
licensePlate: string;
color?: string;
mileage?: number;
}
export interface VehicleUpdateRequest {
color?: string;
mileage?: number;
licensePlate?: string;
}
export interface VehicleResponse {
message: string;
vehicleId: string;
}
export interface PhotoUploadResponse {
photoIds: string[];
urls: string[];
}
export interface ServiceHistory {
serviceId: string;
date: string;
type: string;
cost: number;
description?: string;
}Then remove lines 213-270 from this file and update the import at line 5 to only import Vehicle and ServiceHistory.
Also applies to: 214-270
🤖 Prompt for AI Agents
In src/app/dashboard/vehicles/[vehicleId]/page.tsx (import at line 5) and
duplicate type block at lines 214-270 (also referenced as 213-270), the inline
type declarations conflict with the import causing build errors; create a new
file src/types/vehicle.ts containing the Vehicle, VehicleListItem,
VehicleRequest, VehicleUpdateRequest, VehicleResponse, PhotoUploadResponse, and
ServiceHistory interfaces (include the photos?: string[] property on Vehicle),
update the import at line 5 to import the needed types (Vehicle and
ServiceHistory or others as required) from '@/types/vehicle', and remove the
inline type definitions from page.tsx (delete lines ~213-270) so types are
centralized and no longer redeclared.
| const data = await vehicleService.getVehicleById(vehicleId); | ||
| setVehicle(data); | ||
| setError(null); | ||
| } catch (err: any) { |
There was a problem hiding this comment.
Replace any types with proper error handling.
Three instances of any should be replaced with unknown for better type safety.
Apply this diff:
- } catch (err: any) {
+ } catch (err: unknown) {
+ const message = err && typeof err === 'object' && 'response' in err
+ ? (err as { response?: { data?: { message?: string } } }).response?.data?.message
+ : undefined;
- setError(err.response?.data?.message || 'Failed to load vehicle details');
+ setError(message || 'Failed to load vehicle details');
}Apply similar changes to lines 40 and 54.
Also applies to: 40-40, 54-54
🧰 Tools
🪛 GitHub Check: Install, Lint and Build
[failure] 29-29:
Unexpected any. Specify a different type
🤖 Prompt for AI Agents
In src/app/dashboard/vehicles/[vehicleId]/page.tsx around lines 29, 40 and 54,
replace the catch clause parameter type from "any" to "unknown" and update
subsequent error handling to safely narrow the type before accessing properties:
change catch (err: any) to catch (err: unknown), then when logging or reading
err.message use a type guard (e.g., if (err instanceof Error) { /* use
err.message */ } else { /* fallback: String(err) */ }) or extract a safe string
via String(err); make these three analogous changes at the indicated lines so
you no longer assume the error shape directly.
| {vehicle.photos && vehicle.photos.length > 0 ? ( | ||
| <img | ||
| src={vehicle.photos[0] as unknown as string} | ||
| alt={`${vehicle.make} ${vehicle.model}`} | ||
| className="w-full h-72 object-cover" | ||
| /> | ||
| ) : ( | ||
| <div className="w-full h-72 flex items-center justify-center bg-gray-100 dark:bg-gray-800"> | ||
| <span className="text-gray-500 dark:text-gray-400">No photo available</span> | ||
| </div> | ||
| )} |
There was a problem hiding this comment.
Vehicle interface missing photos property.
Lines 102-124 access vehicle.photos, but the Vehicle interface (lines 214-226) doesn't include a photos property. This will cause runtime errors.
Add photos property to the Vehicle interface:
export interface Vehicle {
vehicleId: string;
customerId: string;
make: string;
model: string;
year: number;
vin: string;
licensePlate: string;
color?: string;
mileage: number;
+ photos?: string[];
createdAt: string;
updatedAt: string;
}Also applies to: 116-124
🧰 Tools
🪛 GitHub Check: Install, Lint and Build
[warning] 103-103:
Using <img> could result in slower LCP and higher bandwidth. Consider using <Image /> from next/image or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element
🤖 Prompt for AI Agents
In src/app/dashboard/vehicles/[vehicleId]/page.tsx around lines 102-112 (and
similarly 116-124), the code accesses vehicle.photos but the Vehicle interface
(lines ~214-226) does not declare a photos property; add a photos property to
the Vehicle interface (e.g., photos?: string[] or photos: string[] depending on
whether photos can be absent) so the code is type-safe, and update any places
that construct or fetch Vehicle objects to include photos (or handle undefined)
accordingly.
| const data = await vehicleService.getMyVehicles(); | ||
| setVehicles(data); | ||
| setError(null); | ||
| } catch (err: any) { |
There was a problem hiding this comment.
Replace any types with proper error handling.
Both error handlers use any. Use unknown with type guards for better type safety.
Apply this diff:
} catch (err: any) {
- setError(err.response?.data?.message || 'Failed to load vehicles');
+ } catch (err: unknown) {
+ const message = err && typeof err === 'object' && 'response' in err
+ ? (err as { response?: { data?: { message?: string } } }).response?.data?.message
+ : undefined;
+ setError(message || 'Failed to load vehicles');
}
// And for handleDelete:
- } catch (err: any) {
- alert(err.response?.data?.message || 'Failed to delete vehicle');
+ } catch (err: unknown) {
+ const message = err && typeof err === 'object' && 'response' in err
+ ? (err as { response?: { data?: { message?: string } } }).response?.data?.message
+ : undefined;
+ alert(message || 'Failed to delete vehicle');Also applies to: 37-37
🧰 Tools
🪛 GitHub Check: Install, Lint and Build
[failure] 22-22:
Unexpected any. Specify a different type
🤖 Prompt for AI Agents
In src/app/dashboard/vehicles/page.tsx around lines 22 and 37, change the catch
clauses that currently use "err: any" to "err: unknown" and add a small type
guard before using the error: check if the value is an instance of Error (or
create an isError function that verifies it has a message property of type
string) then read err.message for logging/handling; for non-Error values,
convert to a string (e.g., String(err)) or use a fallback message. Ensure you do
not assume properties on the unknown error before the guard and preserve
existing control flow (log, set state, or rethrow) after extracting a safe
message.
|
|
||
| ## ✅ **FRONTEND IMPLEMENTATION COMPLETE** | ||
|
|
||
| **Date Completed:** October 17, 2025 |
There was a problem hiding this comment.
Update completion date to match PR creation date.
The document shows "October 17, 2025" but the PR was created on October 31, 2025. Update the date for consistency.
Apply this diff:
-**Date Completed:** October 17, 2025
+**Date Completed:** October 31, 2025 🧰 Tools
🪛 LanguageTool
[style] ~5-~5: Some style guides suggest that commas should set off the year in a month-day-year date.
Context: ...LETE** Date Completed: October 17, 2025 Framework: Next.js 14 with TypeSc...
(MISSING_COMMA_AFTER_YEAR)
🤖 Prompt for AI Agents
In VEHICLE_MANAGEMENT_FRONTEND.md around line 5, the "Date Completed" entry
reads "October 17, 2025" but the PR was created on October 31, 2025; update that
line to "Date Completed: October 31, 2025" so the document matches the PR
creation date and save the file.
…delete vehicle functionality
Summary by CodeRabbit