mirror of
https://github.com/zvx-echo6/navi.git
synced 2026-05-20 22:54:42 +02:00
Add contacts/phone book UI with search integration
New components: - ContactModal.jsx: Save/edit overlay with form fields and soft delete - ContactList.jsx: Contacts tab with filter, create, and tap-to-navigate Modified: - store.js: Add contacts slice (contacts, activeTab, editingContact) - api.js: Add contacts API functions (fetch, create, update, delete, nearby) - config.js: Add has_contacts fallback flag - Panel.jsx: Routes/Contacts tab bar (only when has_contacts enabled) - PlaceDetail.jsx: Save button opens ContactModal, proximity annotation - SearchBar.jsx: Prepend matching contacts before Photon results - App.jsx: Render ContactModal at top level - index.css: Modal overlay, tab bar, contact list item styles Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
03e9780834
commit
3ce860c1e8
10 changed files with 1087 additions and 66 deletions
|
|
@ -6,6 +6,7 @@ import { decodePolyline } from './utils/decode'
|
|||
import MapView from './components/MapView'
|
||||
import Panel from './components/Panel'
|
||||
import PlaceDetail from './components/PlaceDetail'
|
||||
import ContactModal from './components/ContactModal'
|
||||
import LayerControl from './components/LayerControl'
|
||||
import LocateButton from './components/LocateButton'
|
||||
|
||||
|
|
@ -27,14 +28,12 @@ export default function App() {
|
|||
const clearRoute = useStore((s) => s.clearRoute)
|
||||
|
||||
// Fetch route when stops, mode, gpsOrigin, or geoPermission change (debounced 500ms)
|
||||
// NOTE: userLocation is NOT a dep — read from store inside the callback to avoid re-routing on every GPS update
|
||||
useEffect(() => {
|
||||
if (routeDebounceRef.current) clearTimeout(routeDebounceRef.current)
|
||||
|
||||
routeDebounceRef.current = setTimeout(async () => {
|
||||
const { userLocation } = useStore.getState()
|
||||
|
||||
// Build effective stop list
|
||||
let effective = stops.map((s) => ({ lat: s.lat, lon: s.lon }))
|
||||
if (gpsOrigin && geoPermission === 'granted' && userLocation) {
|
||||
effective = [{ lat: userLocation.lat, lon: userLocation.lon }, ...effective]
|
||||
|
|
@ -66,7 +65,7 @@ export default function App() {
|
|||
}
|
||||
}, [stops, mode, gpsOrigin, geoPermission, clearRoute, setRoute, setRouteLoading, setRouteError])
|
||||
|
||||
// Handle maneuver click — fly to that point on the map
|
||||
// Handle maneuver click
|
||||
const handleManeuverClick = useCallback(
|
||||
(maneuver) => {
|
||||
if (!route || !route.legs) return
|
||||
|
|
@ -90,6 +89,7 @@ export default function App() {
|
|||
<MapView ref={mapViewRef} />
|
||||
<Panel onManeuverClick={handleManeuverClick} />
|
||||
<PlaceDetail />
|
||||
<ContactModal />
|
||||
<LayerControl mapRef={mapViewRef} />
|
||||
<LocateButton mapRef={mapViewRef} />
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue