Skip to main content

Visit plans

Pour :Administrateur
Open in Unisoft
The list of visit plans with stat cards on top and an action table.

A visit plan is an ordered route of contacts to meet, prepared beforehand and executed in the field from the mobile app. It replaces the old "tours": stop order automatically optimized, distance and duration computed, progress tracking, notes taken on site.

Access your plan list from the Contacts menu β†’ My plans, or via the URL /app/contact/tournees. On mobile: /mobile/contacts/tournees.

Anatomy of a plan​

A plan is made of:

ElementDescription
NameFree label (Thursday tour, Passover visits Bastille...)
DescriptionOptional text (objective, context)
DatePlanned execution date (optional, used for filtering and tabs)
ProfileTravel mode: On foot, By bike or By car
startLocationDeparture point: your GPS location at creation time, or the organization's address
WaypointsOrdered list of stops (contact + address + lat/lng + order)
Distance / durationComputed by OpenRouteService according to the profile
Polyline (geojson)Route trace displayed on the map
StatusPLANIFIE, EN_COURS, PAUSED, TERMINEE or ARCHIVEE
AuthorUser who created the plan

Each waypoint also stores visitedAt, notes and activityId to track each visit actually done (linked to an entry in the contact's interaction history).

Create a plan​

There are two ways to create a plan, from the contact map:

A. Manual stop selection​

  1. On the map, click New plan in the SubHeader.
  2. The map switches to selection mode (pins get a different outline).
  3. Click the pins to visit. Each selected marker becomes a numbered pink circle.
  4. In the right-side Visit plan panel:
    • Compute itinerary draws the polyline.
    • Optimize reorders the stops to minimize total distance (TSP algorithm).
    • Drag & drop to reorder manually.
  5. Save β†’ modal to name and persist it in the database.

B. All visible contacts​

If your filters narrow the map to 2 to 50 contacts, a panel at the bottom of the filters offers "Create an optimized plan with these contacts β†’ ". One click adds all visible contacts to the plan and launches optimization automatically.

The "My plans" page​

The page /app/contact/tournees lists all your plans with:

Stat cards​

At the top of the page, 5 clickable cards show counters per status:

CardStatus
PlannedPLANIFIE β€” plans created but not yet started
In progressEN_COURS β€” at least one stop visited, plan not finished
PausedPAUSED β€” manually interrupted
CompletedTERMINEE β€” all stops visited or skipped
ArchivedARCHIVEE β€” deleted (soft-delete)

Clicking a card filters the table below.

All / Active / Completed tabs​

Three main tabs for daily sorting:

  • All: no filter
  • Active: PLANIFIE + EN_COURS + PAUSED
  • Completed: TERMINEE

Table​

For each plan, the table shows:

  • Colored avatar + name + description
  • Status (colored chip)
  • Date
  • Number of stops + distance + duration
  • Progress bar: ratio of visited stops over total
  • Author
  • Actions: Rename / Duplicate / Open on the map / Start (mobile) / Delete

Actions​

ActionEffect
RenameOpens a modal to edit name, description, date
DuplicateCreates a copy with (copy) suffixed and status PLANIFIE
Open on the mapNavigates to /app/contact/maps?planId=xxx β€” the plan is reloaded in the RoutePanel, editable and re-launchable
DeleteSoft-delete (transitions to ARCHIVEE); visits already recorded via this plan remain in the contacts' history

Field mode (mobile)​

This is the core of the feature. Once the plan is saved, open it on mobile to execute the tour step by step.

The 'Active plan' screen with polyline, next stop, real-time ETA and the 3 action buttons.

Start a plan​

  1. Open /mobile/contacts/tournees (from the mobile map's list-checks FAB, or from the mobile menu).
  2. Three tabs: Today / Upcoming / Completed.
  3. Tap a PLANIFIE plan β†’ you land on the Active plan screen (/mobile/contacts/tournee-active?id=xxx).

The Active plan screen​

Fullscreen layout (TabBar hidden):

  • Fullscreen map with:
    • The route polyline
    • Numbered waypoints (colored circles based on visited / upcoming / skipped)
    • Your GPS location (pulsing blue circle that follows your motion)
    • followMyLocation enabled: the map periodically recenters on you as you move
  • Minimal transparent header with a back button.
  • At the bottom, the non-dismissible MobNavigationPanel:
    • Step counter Stop 3 of 8
    • Next contact's avatar + name + address
    • Real-time ETA: 5 min Β· 850 m (recomputed by the useGeoTracking hook)
    • 3 action buttons:
ButtonAction
Navigate (blue)Opens native Google Maps (iOS: maps://, Android: https://www.google.com/maps/dir/?api=1&destination=...) in guided navigation toward the stop
Visit done (green)Opens the Visit done sheet (see below)
Skip (gray, skip-forward icon)Moves to the next without marking the visit done β€” the stop stays skipped (not visited, not removed from stats)
  • A floating All stops button opens a drawer listing the whole route, with each stop's status (βœ“ visited, Β· in progress, β—‹ upcoming, β†’ skipped). Tap an item to recenter the map on it.
  • A small X button on the header right cancels the current plan (deletion in database after confirmation).

The "Visit done" sheet​

When you tap Visit done, a sheet rises with:

  • Avatar + contact name
  • Action chips (multi-select): Tefilim, Mezuzah, Discussion, Donation, Study, Moral support Corresponds to the actions[] field of contact_activity entries.
  • Text note: free input area.
  • Voice note: 🎀 button to record up to 15 seconds of audio (WebM/Opus). The audio is uploaded then automatically transcribed by Whisper STT on the server side; the transcription is appended to the text note.

On tap on Confirm visit:

  1. The audio (if any) is uploaded via POST /tournees/:id/voice-note.
  2. A contact_activity entry of type Visite is created with the current user as author, the selected actions, and the note (text + transcription).
  3. The waypoint moves to visitedAt: now.
  4. The navigation panel automatically jumps to the next unvisited stop.

Automatic status transitions​

The server handles status transitions without intervention:

PLANIFIE β†’ EN_COURS (on first visit-done)
EN_COURS β†’ TERMINEE (when the last stop is visited or skipped)

You can also force manually:

  • Pause: POST /tournees/:id/pause (status β†’ PAUSED, the mobile app can be closed and resumed later without losing progress).
  • Cancel: DELETE /tournees/:id (soft-delete, status β†’ ARCHIVEE).

Visit tracking in the contact profile​

Each visit done via a plan creates a standard entry in the Activities tab of the contact, identical to a visit entered from the profile. Specific metadata:

  • type: "Visite"
  • tourneeId (link to the plan)
  • actions[] (selected chips)
  • commentaire (text note + transcription)
  • audioUrl (if there is a voice note)
  • auteur (logged-in user)

Consequence: a contact visited via a plan sees their last-visit chip on the map update automatically (turns green).

Typical use cases​

Prepare the weekly tour​

  1. Open the map on Thursday morning.
  2. Last visit coloring mode: spot the red and purple contacts around you.
  3. New plan β†’ select 8-10 contacts on foot.
  4. Optimize β†’ the order is reorganized in a minimal loop.
  5. Save as Thursday tour week 21.
  6. On tour morning, open the mobile app β†’ My plans β†’ tap the plan β†’ Start.

Collective neighborhood visit for a holiday​

  1. Filter the map by category Passover_Family.
  2. If fewer than 50 contacts: Create an optimized plan with these contacts β†’.
  3. Profile: By car for a distribution.
  4. Save, duplicate for each day of the holiday, start.

Prepare an unplanned visit​

  1. On the map, tap a pin.
  2. Navigate button in the popup β†’ opens Google Maps directly (no need to create a plan).

Permissions and multi-tenant​

  • Access to the map and plans requires the contact.read permission.
  • Creating / modifying / deleting a plan requires contact.write.
  • Plans are strictly isolated per organization: the backend always filters on organisation = res.org.id and returns 404 (not 403) if you try to access a plan from another organization, to avoid leaking the existence of an id.

Limitations​

  • Max 50 stops per plan (free OpenRouteService quota limit).
  • Daily optimization quota: 2,500 calls / day, across all users. Beyond that, the Optimize button returns an error until the next day.
  • Voice note: maximum 15 seconds; the format depends on the browser (usually WebM/Opus, M4A on Safari iOS).
  • Whisper transcription: the service is self-hosted; in case of unavailability, the audio is kept and a Retry button appears.
  • Offline: field mode requires a connection (status updates and audio uploads are synchronous). An offline mode with a sync queue is planned for a future version.
  • No drag&drop in the RoutePanel on mobile (desktop only): reorganizing a plan is done from the web version.