feat: migrate Angular 16 frontend to React 18 + TypeScript#3
feat: migrate Angular 16 frontend to React 18 + TypeScript#3devin-ai-integration[bot] wants to merge 2 commits into
Conversation
- Replace Angular CLI with Vite build tool - Implement React 18 with TypeScript, React Router v6, React Query, react-hook-form - Create data models, API layer with Axios, React Query hooks - Build all page components: Owners, Pets, Visits, Vets, PetTypes, Specialties - Add shared Navbar and Layout components with Bootstrap 3 styling - Configure client-side routing matching original Angular routes - Update Dockerfile to Node 20 with Nginx SPA fallback - Update README with new tech stack documentation - Remove all Angular source files, configs, and e2e tests
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
| <Route path="/owners/:id/pets/add" element={<PetAdd />} /> | ||
| <Route path="/owners/:ownerId/pets/:petId/edit" element={<PetEdit />} /> | ||
| <Route path="/owners/:ownerId/pets/:petId/visits/add" element={<VisitAdd />} /> | ||
| <Route path="/pets/:petId/edit" element={<PetEdit />} /> |
There was a problem hiding this comment.
🔴 PetEdit breaks on /pets/:petId/edit route due to missing ownerId param
The PetEdit component destructures ownerId from useParams (src/pages/pets/PetEdit.tsx:14), but the route at src/App.tsx:37 (/pets/:petId/edit) does not include an ownerId segment. When this route is matched, ownerId is undefined, causing: (1) Number(ownerId) → NaN sent in the API request body (PetEdit.tsx:43), making the update request malformed; (2) the Back button navigates to /owners/undefined (PetEdit.tsx:95); (3) success redirect goes to /owners/undefined (PetEdit.tsx:46).
Prompt for agents
The route /pets/:petId/edit renders PetEdit which requires ownerId from URL params, but this route does not include ownerId. The PetEdit component at src/pages/pets/PetEdit.tsx:14 destructures ownerId from useParams, but it will be undefined on this route.
Two possible fixes:
1. Remove the /pets/:petId/edit route from App.tsx if it's not needed (since /owners/:ownerId/pets/:petId/edit already exists).
2. Make PetEdit resilient to a missing ownerId by falling back to pet.ownerId from the fetched pet data. In the onSubmit handler, use pet?.ownerId instead of Number(ownerId) when ownerId is undefined. Similarly, update the Back button and success navigation to use pet?.ownerId as a fallback.
The same pattern applies to the /pets/:petId/visits/add route and the VisitAdd component.
Was this helpful? React with 👍 or 👎 to provide feedback.
| <Route path="/owners/:ownerId/pets/:petId/edit" element={<PetEdit />} /> | ||
| <Route path="/owners/:ownerId/pets/:petId/visits/add" element={<VisitAdd />} /> | ||
| <Route path="/pets/:petId/edit" element={<PetEdit />} /> | ||
| <Route path="/pets/:petId/visits/add" element={<VisitAdd />} /> |
There was a problem hiding this comment.
🔴 VisitAdd breaks on /pets/:petId/visits/add route due to missing ownerId param
The VisitAdd component destructures ownerId from useParams (src/pages/visits/VisitAdd.tsx:12), but the route at src/App.tsx:38 (/pets/:petId/visits/add) does not include ownerId. When this route is matched, ownerId is undefined, causing: (1) Number(ownerId) → NaN passed to addVisit(NaN, petId, visit), producing a request to owners/NaN/pets/${petId}/visits (src/api/visitApi.ts:15) which will fail; (2) Back button and success redirect navigate to /owners/undefined (VisitAdd.tsx:80,25).
Was this helpful? React with 👍 or 👎 to provide feedback.
| <div>No owners with LastName starting with "{searchTerm}"</div> | ||
| )} | ||
|
|
||
| {owners && owners.length > 0 && ( |
There was a problem hiding this comment.
🟡 'Add Owner' button hidden when owner list is empty, preventing creation of first owner
The "Add Owner" button is rendered inside the {owners && owners.length > 0 && ...} conditional block at src/pages/owners/OwnerList.tsx:51. When there are zero owners in the system (e.g., fresh database), the button is not rendered and there is no other navigation to /owners/add in the UI (the navbar only has a link to /owners). This is a regression from the old Angular code where the button was shown whenever data was received, regardless of count. Users with an empty database cannot add their first owner through the UI.
| {owners && owners.length > 0 && ( | |
| {owners && owners.length > 0 && ( |
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Complete rewrite of the Spring PetClinic frontend from Angular 16 to React 18 + TypeScript. The backend REST API (
http://localhost:9966/petclinic/api/) is unchanged.New tech stack: Vite, React Router v6, React Query (@tanstack/react-query), react-hook-form, Axios, Bootstrap 3.
What changed:
src/app/), config (angular.json,karma.conf.js, etc.), and e2e tests deletedsrc/models/,src/api/,src/hooks/,src/pages/,src/components/try_files)src/assets/topublic/Updates since last revision
OwnerDetail.tsxnow navigates to/owners/${id}/pets/${pet.id}/editand/owners/${id}/pets/${pet.id}/visits/add, correctly supplyingownerIdto downstream components.navigate(-1 as unknown as string)in favor ofnavigate(-1).sedcommand for the listen port, sinceprintfoverwritesdefault.confentirely.Review & Testing Checklist for Human
App.tsxstill defines fallback routes/pets/:petId/editand/pets/:petId/visits/add(without:ownerIdin the path). If a user navigates to these URLs directly,ownerIdwill beundefined, causing broken API calls inPetEditandVisitAdd. Consider removing these fallback routes or adding guards.ownerApi.ts,petApi.ts,visitApi.ts, etc.) matches the actual Spring PetClinic REST endpoints. EspeciallyaddPet→POST owners/${ownerId}/petsandaddVisit→POST owners/${ownerId}/pets/${petId}/visits.npm testscript exists but will find no test files.spring-petclinic-rest, runnpm run dev, and verify: owner search/add/edit/delete, pet add/edit from owner detail, visit add/edit, vet list/add/edit, pet types CRUD, specialties CRUD. Delete operations have no confirmation dialog — verify this is acceptable.Notes
.envis committed withVITE_REST_API_URL=http://localhost:9966/petclinic/api/(not a secret, but worth noting)npm run build,npm run lint)Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/f01a71fe45ab4c7aa55bc86885cd0382