Repository navigation
feat(api): contract types and adapters for trips and trip photos - #38
Conversation
contract.ts mirrors the backend OpenAPI draft 0.0.5. The mock now answers trips and trip photos in contract shapes, so the mock and the real backend go through the same adapters and the screens see one format. Adds photo, upload-item and batch adapters with tests, image expiry fields, and a nullable uploaded_at.
|
During live integration testing, I noticed that the Dashboard still displayed mock statistics and recently uploaded photos alongside persistent trip records. Those demonstration photos did not belong to the authenticated user's trips. I've updated I also added regression tests for both modes, including an assertion that the frontend does not request the unimplemented This keeps the change within the existing adapter architecture without introducing new feature flags or expanding the backend integration scope. |
kctong529
left a comment
There was a problem hiding this comment.
I've completed the verification of PR #38 against backend feat/trip-persistence.
Automated tests — all passed:
- Live trip creation, retrieval, listing, and response adaptation.
- Authentication, input validation, and expected error responses.
- Bidirectional ownership isolation using two distinct Firebase accounts.
- Mock/live Dashboard summary regression tests.
- Existing frontend acceptance tests, type checks, linting, and build.
Manual verification:
- Trips persist after restarting the Go backend.
- Different Firebase accounts cannot list or retrieve each other's trips, including through direct URLs.
- Persistent trips render correctly in the frontend.
The README has also been updated to document the integration boundaries, test configurations, and remaining mock-backed features.
The adapter architecture looks sound, and I don't see any remaining blockers within this PR's scope. The unfinished photo, map, and sharing integrations can proceed separately.
Thanks, Kristian, for the original implementation! I'm happy to approve and merge this PR.
Part of #20
contract.ts mirrors the backend OpenAPI draft 0.0.5. The mock now answers trips and trip photos in contract shapes, so the mock and the real backend go through the same adapters and the screens see one format. Adds photo, upload-item and batch adapters with tests, image expiry fields, and a nullable uploaded_at.
Suggested new body:
Summary
Introduce a shared API contract and adapter layer for incremental integration between the React frontend and Go backend.
Screens access data through
src/api/client.ts, which selects live or mock implementations per endpoint. Backend responses are converted into frontend view models through dedicated adapters, keeping API-specific structures out of UI components.Changes
API contracts and adapters
Separate backend API representations from frontend view models:
src/api/contract.ts— Defines TypeScript interfaces based on the backend's OpenAPI specification (draft 0.0.5), covering trips, photos, pagination, upload registration, signed upload targets, processing batches, and API errors. Fields anticipated by the frontend design but not yet defined in OpenAPI are marked optional.src/api/types.ts— Defines frontend-facing models consumed by React components, independently of the backend's wire format.src/api/adapters.ts— Converts API responses into frontend models, normalizing field differences and supplying neutral defaults where backend data is not yet available.src/api/http.ts— Centralizes HTTP requests, Firebase ID token handling and refresh, and structured API errors.src/api/client.ts— Provides the data-access interface used by screens, selecting live or mock implementations independently for each endpoint.This separation allows backend endpoints to be integrated incrementally without coupling UI components to the API's representation.
The contract definitions also prepare for future photo and upload integration. In particular, they distinguish original EXIF coordinates from effective locations after user correction, represent accepted and rejected upload files, and establish cursor-based pagination structures.
These are TypeScript declarations rather than runtime validation schemas. Defining a contract does not imply that its corresponding endpoint is already implemented.
Live trip integration
Connect three operations to the Go backend when
VITE_API_URLis configured:GET /api/tripsPOST /api/tripsGET /api/trips/{id}The frontend attaches Firebase ID tokens to authenticated requests and converts backend responses into its existing trip models.
These operations have been verified against backend
feat/trip-persistence, which provides PostgreSQL-backed, owner-scoped trip records when database-backed user resolution is enabled.Mock/live data boundaries
Prevent unrelated demonstration data from appearing alongside persistent trip records:
getSummary()returnsnullwhen trip operations are live butGET /api/me/summaryis unavailable, rather than falling back to mock statistics and photos.Map data, uploads, place search, location correction, and other unintegrated operations remain mock-backed.
Testing
Introduce separate Playwright suites for live API integration and mock/live boundary regression, alongside the existing frontend acceptance tests.
Live API integration —
npm run test:integrationMock/live boundary regression —
npm run test:boundariesThe existing mock-based acceptance tests remain independent of the live integration suite.
Verification completed:
Documentation
Update the README to clarify the current backend integration status, API boundaries, Firebase identity resolution, test configurations, and known limitations.
Remaining work
These are follow-up integrations and remain outside the scope of this PR.