This repository has been archived on 2026-03-09. You can view files and clone it, but cannot push or open issues or pull requests.
as-app/plans/PLAN_DAE-gpt.md
2026-03-07 07:53:08 +01:00

17 KiB
Raw Blame History

DAE / Defibrillator integration plan (agent-splittable)

Common plan prefix (include this at the top of every coding-agent prompt)

Product goal

Integrate defibrillator (DAE) discovery into the app using the embedded SQLite DB query helper getNearbyDefibs(). Provide:

  • A new left-drawer link to a new view DAEList.
  • In an active alert Situation view, a button Afficher les défibrillateurs that:
    1. enables DAE display around the 10km corridor around the segment between user location and alert location,
    2. then navigates to the alert map.
  • In alert map, render DAE markers; tapping a DAE opens DAEItem.
  • DAEList screen with bottom navigation: Liste (default) and Carte, showing defibs nearest→farthest around the user, within 10km.
  • DAEItem screen with bottom navigation: Infos (default) and a map/itinerary to reach the selected DAE (mimic alert routing).
  • During alert posting, if a cardiac-related keyword is detected in the alert subject, show a persistent modal (must remain on top even after redirect to the alert view, and must work offline) with two actions:
    • Chercher un défibrillateur → go to DAEList
    • Non merci → dismiss

v1 decisions already made

  1. Availability filter: only use disponible_24h === 1 for now; no parsing of horaires string yet (later iteration).
  2. Corridor filter: within 10km of the user↔alert segment (not union of circles).
  3. Location permission denied: use last-known location; if none, show an explanatory empty state (no hard block).

Known architecture + relevant anchors in codebase

Data model (canonical Defib object for UI)

Base DB row shape (from repo select) is:

  • id: string
  • latitude: number
  • longitude: number
  • nom: string
  • adresse: string
  • horaires: string (unused in v1)
  • acces: string
  • disponible_24h: 0|1
  • plus computed distanceMeters: number

Represent coordinates consistently as:

Filtering logic requirements

Near-user list (DAEList):

  • Input: user location (current if available, else last-known)
  • Filter: distance ≤ 10_000m
  • Sort: nearest→farthest
  • Availability: if disponible_24h === 1 keep; else exclude in v1 (until horaires parsing)

Alert-axis corridor overlay (Alert map + Situation button):

  • Input: user location + alert location
  • Filter: points within corridorMeters = 10_000 of the line segment user→alert
  • Also restrict to a sensible max radius around user to limit query size (see “Query strategy” below)

Corridor math recommendation:

  • Use existing Turf dependency already present in map stack: @turf/helpers lineString(), @turf/nearest-point-on-line nearestPointOnLine(), and a distance function (geolib or Turf distance).

Query strategy (performance + offline)

Use the existing local SQLite query API (no network) via getNearbyDefibs().

  • For near-user list: query radiusMeters = 10_000, limit = e.g. 200500 (tune later).
  • For corridor overlay:
    • First query a radius around the midpoint or around user large enough to include the whole segment + corridor.
    • Practical v1 approach: compute segmentLengthMeters and query radius = segmentLengthMeters/2 + corridorMeters around the midpoint.
    • Then apply corridor filter in JS and cap results to a max marker count (e.g. 200) to keep map responsive.

Navigation and UX conventions

  • Drawer items come from <Drawer.Screen> options in src/navigation/Drawer.js and are rendered by menuItem(). Hidden routes should set options.hidden = true.
  • Bottom tab patterns exist (see alert tabs in src/scenes/AlertCur/Tabs.js).
  • For “persistent modal on top even after redirect”, implement modal at a global provider level (within LayoutProviders tree) using Portal so it survives navigation.

Split tasks (agent-ready prompts)

Each task below is designed to be handed to a coding agent. Include the Common plan prefix above in every prompt.

Task 1 — Validate embedded DB asset packaging and repo schema assumptions

Objective: Ensure the bundled SQLite geodae.db is present and accessible on-device, and confirm schema columns used by defibsRepo exist.

Implementation notes:

  • initDb() copies require('../assets/db/geodae.db') to documents.
  • Current workspace shows src/assets/db/ empty; find where DB is stored or add it.

Acceptance criteria:

  • App can open DB without throwing at require('../assets/db/geodae.db').
  • Query SELECT ... FROM defibs works with columns: id, latitude, longitude, nom, adresse, horaires, acces, disponible_24h and h3.

Likely files touched:


Task 2 — Define and implement defib filtering utilities (10km near-user + 10km corridor)

Objective: Create pure utility functions to:

  • compute query radius for corridor overlay
  • filter a list of defibs to those inside corridor
  • normalize coordinates and compute distances

Implementation notes:

Suggested exports:

  • computeCorridorQueryRadiusMeters({ userLonLat, alertLonLat, corridorMeters })
  • filterDefibsInCorridor({ defibs, userLonLat, alertLonLat, corridorMeters })
  • toLonLat({ latitude, longitude })

Acceptance criteria:

  • Given synthetic points, corridor filter behaves as “distance to segment ≤ 10km”.

Likely files touched:


Task 3 — Add a Defibs store (zustand atom) to manage caching + overlay enablement + modal state

Objective: Add centralized state to avoid repeated DB queries and to coordinate UI across screens.

State concerns:

  • cached near-user defibs list
  • cached corridor defibs for current alert id
  • flag showDefibsOnAlertMap (or defibsOverlayEnabledByAlertId)
  • selected defib id for DAEItem
  • “DAE suggestion modal” visibility (global)

Integration points:

Acceptance criteria:

  • Other tasks can simply call actions like defibsActions.loadNearUser() and defibsActions.enableCorridorOverlay(alertId).

Likely files touched:


Task 4 — Add navigation routes: DAEList in drawer + DAEItem as hidden route

Objective: Add new screens to navigation so they can be opened from:

  • left drawer (DAEList)
  • map marker press (DAEItem)
  • modal CTA (DAEList)

Implementation notes:

Acceptance criteria:

  • A new drawer link navigates to DAEList.
  • DAEItem route can be navigated to programmatically.

Likely files touched:


Task 5 — Situation button on active alert: enable DAE overlay and navigate to alert map

Objective: In Situation view for current alert, add button Afficher les défibrillateurs.

Behavior:

  1. Determine user coords (prefer current; fall back to last-known as in alert maps useLocation usage in src/scenes/AlertCurMap/index.js).
  2. Query defibs from DB with a computed radius around midpoint.
  3. Filter to corridor (10km).
  4. Store result + enable overlay flag.
  5. Navigate to map tab: Main → AlertCur → AlertCurTab → AlertCurMap (same pattern used in AlertCurOverview).

Acceptance criteria:

  • Button exists only when alert has coordinates.
  • After tap, map opens and defib markers appear.

Likely files touched:


Task 6 — Alert map: render DAE markers and open DAEItem on tap

Objective: Display defib markers as a separate feature layer on alert map.

Implementation notes:

  • Existing feature system creates a GeoJSON FeatureCollection for alerts in useFeatures().
  • Add DAE features when overlay is enabled.
  • Add a new marker icon to map images by extending FeatureImages.
  • Update press handler in useOnPress() to recognize properties.defib and navigate to DAEItem.

Acceptance criteria:

  • Markers appear/disappear based on overlay flag.
  • Tapping a marker navigates to DAEItem.
  • Clustering behavior is acceptable (either include in cluster or keep separate; v1 can skip clustering by rendering as a separate layer).

Likely files touched:


Task 7 — Implement DAEList screen with bottom tabs: List (default) + Map

Objective: Create DAEList scene with bottom navigation and two tabs:

  • Liste: list view nearest→farthest
  • Carte: map view of same defibs

Behavior:

  • Load near-user defibs within 10km using getNearbyDefibs().
  • Filter by availability: keep disponible_24h === 1 only.
  • If no location available, show empty state with explanation.
  • Tapping list item navigates to DAEItem.

Implementation notes:

Acceptance criteria:

  • Drawer link opens DAEList.
  • List is sorted by distanceMeters.
  • Map tab renders markers.

Likely files touched:


Task 8 — Implement DAEItem screen with bottom tabs: Infos (default) + Go-to map (itinerary)

Objective: Create DAEItem detail view for a selected defib.

Tabs:

  • Infos: name, address, access, availability badge
  • Carte: show route from user to DAE, mimicking alert routing implementation in AlertCurMap

Implementation notes:

  • Reuse route calculation patterns (OSRM URL building, polyline decode, step list components) from alert map.
  • Route target is defib coordinates instead of alert coordinates.

Acceptance criteria:

  • From any entrypoint (alert map marker or list), DAEItem shows correct defib.
  • Itinerary works when online; offline behavior is a clear message (route unavailable offline).

Likely files touched:


Task 9 — Keyword detection while posting an alert + persistent DAE suggestion modal

Objective: Detect cardiac-related terms during alert posting and display a global modal that remains visible even after navigation.

Detection requirements:

  • Keywords include: cardiaque, cardiac (typos), coeur, malaise, inconscient, évanoui etc.
  • Should run locally/offline.

Implementation approach (recommended):

  • Use fuzzy matching with Fuse (already used in findAlertTitle()) or implement a lightweight normalization + substring/levenshtein.
  • Trigger detection in the confirm submit flow, before/around navigation in onSubmit().
  • Render modal at app root using react-native-paper Portal inside LayoutProviders so it persists across navigation.

Modal UI:

  • Title/text: explain quickly why looking for a DAE matters.
  • Two buttons:
    • Chercher un défibrillateur → navigate to DAEList
    • Non merci → dismiss

Acceptance criteria:

  • Modal shows for matching terms even with no internet.
  • Modal stays visible after redirect to current alert view.

Likely files touched:


Task 10 — Verification checklist (manual) + minimal automated coverage

Objective: Provide a deterministic checklist and (where feasible) simple automated tests.

Manual verification checklist:

  1. Drawer: DAE link visible, opens list.
  2. DAEList:
    • permission granted → list populated, sorted
    • permission denied + last-known available → list uses last-known
    • permission denied + no last-known → empty state
  3. Alert Situation button: enables overlay and opens alert map.
  4. Alert map: DAE markers render; tap → DAEItem.
  5. DAEItem routing: online route works; offline shows message.
  6. Keyword modal:
    • trigger term in subject → modal shows
    • redirect to alert occurs and modal remains on top
    • CTA navigates to DAEList

Acceptance criteria:

  • Checklist documented and reproducible.

Likely files touched:


Mermaid overview

flowchart TD
  A[User posts alert] --> B[Keyword detection]
  B -->|match| M[Show persistent DAE modal]
  B -->|no match| C[Navigate to AlertCur Situation]
  M --> C
  M -->|Chercher un defibrillateur| L[DAEList]
  M -->|Non merci| C
  C --> S[Button Afficher les defibrillateurs]
  S --> E[Enable overlay in store]
  E --> MAP[AlertCurMap]
  MAP -->|tap DAE marker| ITEM[DAEItem]
  L -->|tap list item| ITEM