Some checks failed
Deploy / Build Web Image (push) Failing after 19s
E2E Tests / Playwright E2E (push) Failing after 25s
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 8s
CI / E2E Tests (push) Has been skipped
Deploy / Build API Image (push) Failing after 22s
Deploy / Build AI Services Image (push) Failing after 18s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Security Scanning / Dependency Audit (pnpm) (push) Failing after 15s
Security Scanning / Trivy Scan — API Image (push) Failing after 1m31s
Security Scanning / Trivy Scan — Web Image (push) Failing after 40s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 34s
Security Scanning / Trivy Filesystem Scan (push) Failing after 21s
Security Scanning / Security Gate (push) Failing after 1s
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 1m4s
User feedback: typing lat/lng by hand is painful — wire a real map
picker.
New component apps/web/components/map/location-picker.tsx:
- Mapbox map with theme-synced style (uses useMapboxStyle).
- Draggable primary marker (custom pin, inner-wrapped so Mapbox's
translate isn't clobbered — follows the hover-fix pattern we shipped
last commit).
- Click anywhere on the map → marker jumps + onChange fires.
- Dragend → onChange fires.
- Search box using Mapbox Geocoding API
(/geocoding/v5/mapbox.places) scoped to country=vn, language=vi,
limit=5, debounced 350ms with AbortController. Clicking a suggestion
centers the map + fills the resolved { address, ward, district,
city } from feature.context.
- Graceful fallback when NEXT_PUBLIC_MAPBOX_TOKEN is missing.
- Inline help "Nhấp vào bản đồ hoặc kéo pin để chọn vị trí".
StepLocation (listing-form-steps.tsx):
- New optional `setValue` + `watch` props. When both are passed the
picker renders and wires lat/lng (+ address/ward/district/city from
geocoder) into the form. Without them, the Step falls back to the
manual-only layout (kept for callers that don't want the picker).
- Dynamic-import the picker with ssr:false so mapbox-gl stays out of
the server bundle.
Wired into:
- /listings/new page — picker enabled on Step 2 (Vị trí).
- /listings/[id]/edit page — picker enabled on the Location tab, with
latitude/longitude now hydrated from property.latitude/longitude.
Test fixture update: listing-form-steps.spec.tsx no longer asserts the
placeholder string — instead verifies the lat/lng inputs still render
when the picker is absent (setValue not supplied), matching the new
opt-in contract.
Verification
- Typecheck clean across touched files.
- 624 / 624 web tests pass.
- Preview smoke: /listings/<id>/edit → Vị trí tab renders map +
draggable pin + search, lat/lng prefilled from listing data.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>