Éditeur visuel de séquences de relance patient pour laboratoires d'anatomopathologie. Le chef de laboratoire dessine son protocole de relance (email, SMS, WhatsApp, courrier postal) sous forme de graphe, l'assigne à des patients, et suit son déroulement — comme dans n8n ou Zapier.
Mini-projet réalisé en réponse au brief d'entretien RainPath (
docs/subject.txt). Aucun envoi réel — tous les canaux sont factices, sans provider, sans authentification.Note de naming : « CallPath » est le nom produit affiché à l'utilisateur. Le code interne et l'API continuent à parler de
workflow— c'est volontaire (le rename produit est cosmétique, le modèle de données reste stable).
Prérequis : Docker (Compose v2) et make.
make up # build + démarre back + front + Prisma Studio
make down # stop (volume SQLite conservé)
make re # down + up — redémarrage rapide du stack
make refront # rebuild propre du frontend (utile après edit deps)
make back_tests # lance les tests backend (unit validator + e2e HTTP)
make front_tests # lance les tests frontend (Vitest + RTL)
make dclean # wipe DB + re-seed (1 structure + 9 node_types + 42 patients + 3 CallPaths démo)Une fois make up lancé :
| URL | Quoi |
|---|---|
| http://localhost:5173 | Frontend — landing → dashboard |
| http://localhost:3000/api/v1/health | Health-check backend |
| http://localhost:3000/api/docs | Swagger UI (OpenAPI) |
| http://localhost:5555 | Prisma Studio (lecture/écriture DB) |
À la première visite, le seed peuple la DB de 42 patients fictifs et 3 brouillons de CallPath démontrant des cadences différentes (3 jours, 1 semaine, 30 jours).
Le dashboard récapitule l'atelier : CallPaths actifs (en cours sur des patients), brouillons (en construction), patients en relance, total patients. Chaque carte affiche le mini-graphe du CallPath — on reconnaît la séquence d'un coup d'œil, sans ouvrir.
L'éditeur est un canvas React Flow avec palette à gauche
(neuf types de nœuds : start / wait / 4 send / 2 condition / end),
inspecteur à droite (formulaires typés par node, validation
zod), et un bandeau de validation en haut. Drag-and-drop ou
raccourcis clavier (W email, T SMS, H WhatsApp, P postal,
C condition, M attente). Conditions à deux sorties true /
false ; éditeur d'arêtes ; copier-coller ; undo / redo ; aide
overlay sur ?.
Quand un CallPath est validé, on l'active : la palette laisse
sa place à un panneau « Patients assignés », et une modale
« Nouvel envoi » permet d'assigner un groupe de patients à la
séquence. Chaque assignation devient un batch suivi
indépendamment ; un dossier patient (route /patients/:id)
visualise l'avancement individuel.
Raccourcis clavier — la liste complète
| Touche | Action |
|---|---|
W |
Ajouter un nœud Envoi email |
T |
Ajouter un nœud Envoi SMS |
H |
Ajouter un nœud Envoi WhatsApp |
P |
Ajouter un nœud Envoi postal |
M |
Ajouter un nœud Attente |
C |
Ajouter un nœud Condition |
Ctrl+C / Ctrl+V |
Copier / coller un nœud |
Ctrl+Z / Ctrl+Shift+Z |
Undo / redo |
Suppr / Backspace |
Supprimer la sélection |
( / ) |
Toggle panneau gauche / droit |
? |
Overlay d'aide |
Désactivés en mode active et sur écrans < sm.
| Couche | Choix | Raison |
|---|---|---|
| Frontend | Vite + React 18 + TypeScript | Stack imposée par le sujet ; Vite pour le HMR. |
| Éditeur graphe | React Flow (@xyflow/react) |
Standard de l'écosystème n8n-like, custom node types documentés, Background / Controls / MiniMap inclus. |
| Styles | Tailwind + design system maison | Identité éditoriale-médicale (Fraunces / Geist / JetBrains Mono · ink + ochre). Cf. docs/plan/design_system.md. |
| State | TanStack Query (server) + Zustand (UI) | Zustand uniquement pour le canvas + l'inspecteur (sélection partagée). |
| Formulaires | react-hook-form + zod |
Miroir des DTO backend → un seul source-of-truth de forme. |
| Backend | NestJS 10 + Prisma + SQLite | Stack imposée. SQLite suffit (mini-projet mono-tenant). |
| Validation graphe | Service WorkflowValidator testé unitairement |
10+ codes d'erreur stables, exposés via POST /workflows/:id/validate. |
| API | REST /api/v1/... + Swagger |
URI versioning natif NestJS ; documenté via @nestjs/swagger. |
| Tests | Jest (back, unit + e2e Supertest) · Vitest + RTL (front) | Validateur testé unitairement ; 88 specs front sur helpers purs (serializer, estimate-duration, mini-graph helpers, deriveCopyName, relative-fr), store + invalidations (editor-store, useInvalidate), composants critiques (TitleField, ErrorsBanner, WorkflowCardMenu, BatchHeader, BatchActionsMenu, AssignmentsHeader, useBatches, useNodeErrors, translateError). |
| Orchestration | Docker Compose + Makefile racine |
Une commande, deux services, un volume DB persistant. |
Structure (1 tenant démo)
└── Workflow ("CallPath")
├── WorkflowNode (start | wait | send_* | condition_* | end)
├── WorkflowEdge (branch: 'true' | 'false' | null)
└── WorkflowVersion (snapshot JSON immuable)
Patient ◄── WorkflowAssignment ──► Workflow
└── currentNodeId (position dans le graphe)
Détails : backend/prisma/schema.prisma et
docs/plan/plan_sessions/ (chaque évolution de schéma est tracée).
| Méthode | Route | Description |
|---|---|---|
GET |
/api/v1/workflows |
Liste des CallPaths (avec mini-graphe + compteurs) |
GET |
/api/v1/workflows/:id |
Un CallPath complet (graphe + métadonnées) |
POST |
/api/v1/workflows |
Crée un brouillon |
PUT |
/api/v1/workflows/:id |
Sauvegarde le graphe (wipe + insert atomique) |
PATCH |
/api/v1/workflows/:id/status |
draft ⇄ active |
POST |
/api/v1/workflows/:id/validate |
Dry-run validateur, retourne erreurs structurées |
DELETE |
/api/v1/workflows/:id |
Soft-delete |
GET |
/api/v1/patients |
Liste des patients |
POST |
/api/v1/workflows/:id/assignments |
Assigne un batch de patients |
GET |
/api/v1/node-types |
Catalogue des 9 types de nœuds |
Documentation complète et navigable : http://localhost:3000/api/docs.
call_path/
├── frontend/ # Vite + React + TS
│ ├── src/
│ │ ├── App.tsx # router : /, /dashboard, /workflows/:id, /patients/:id
│ │ ├── api/ # client typé adossé à /api/v1
│ │ └── features/
│ │ ├── landing/ # page d'accueil éditoriale (/)
│ │ ├── workflow-list/ # dashboard (/dashboard)
│ │ ├── workflow-editor/ # éditeur de graphe
│ │ │ ├── canvas/ # React Flow + nodes custom
│ │ │ ├── palette/ # liste draggable des node_types
│ │ │ ├── inspector/ # formulaires propriétés
│ │ │ ├── toolbar/ # save / validate / activate
│ │ │ ├── assignments/ # panneau Patients assignés
│ │ │ ├── validation/ # mapping codes → messages FR
│ │ │ └── help/ # overlay raccourcis
│ │ └── patient-folder/ # dossier patient + progression
│ └── public/tutorial/ # screenshots du README
│
├── backend/ # NestJS + Prisma
│ ├── src/
│ │ ├── main.ts # bootstrap (CORS, ValidationPipe, Swagger)
│ │ ├── workflows/ # module métier principal
│ │ │ ├── workflows.controller.ts
│ │ │ ├── workflows.service.ts
│ │ │ ├── workflows.validator.ts # règles graphe (testé unit)
│ │ │ ├── validator/rules/ # règles atomiques composables
│ │ │ └── dto/ # DTOs class-validator
│ │ ├── patients/ # CRUD patients
│ │ ├── assignments/ # assignations + batches
│ │ ├── node-types/ # catalogue (read-only)
│ │ └── common/ # filters, decorators, constants
│ └── prisma/
│ ├── schema.prisma # 9 modèles, mappings @@map
│ └── seed.ts # structure + node_types + 42 patients + 3 CallPaths démo
│
├── infra/
│ └── docker-compose.yml # 2 services (backend, frontend), volume SQLite
│
├── docs/
│ ├── subject.txt # brief original RainPath
│ ├── nodes_explanation.md # familles de nœuds + sémantique délai
│ ├── plan/
│ │ ├── backend_foundations.md # architecture, standards, séquence sessions
│ │ ├── frontend_foundations.md # idem côté front
│ │ ├── design_system.md # identité visuelle (prescriptif)
│ │ └── plan_sessions/ # plans détaillés par session
│ └── sessions/ # 20+ comptes-rendus de session
│
├── Makefile
└── README.md
La section 8 du brief insiste là-dessus : « aide-toi au maximum des agents IA pour réaliser le projet ». Voilà la méthode que j'ai appliquée, et où elle laisse des traces dans le repo.
Boucle de travail, feature par feature :
- Cadrage — j'écris ce que je veux et les contraintes ; Claude répond avec un plan (architecture, étapes, fichiers touchés). Je relis, je corrige, je tranche.
- Exécution — Claude implémente le plan, étape par étape. Je revois chaque diff, je teste, je redirige si ça part de travers.
- Compte-rendu — à la fin de la claude session de travail, un log résume pour donner du context pour la prochain session.
Les traces dans docs/ :
docs/plan/— les plans avant exécution (architecture, design system, plans détaillés par session). C'est ce que je voulais faire avant d'écrire la première ligne.docs/sessions/— 20+ comptes-rendus chronologiques, un par session. C'est ce qui s'est réellement passé : décisions, trade-offs, bugs rencontrés, ce qui a été reporté.docs/subject.txt— le brief original RainPath.docs/nodes_explanation.md— sémantique des nœuds (rédigé pour clarifier le modèle avec Claude avant d'écrire le validateur).
Lire un plan suivi de son compte-rendu de session donne une bonne idée de comment j'oriente l'agent, où je le laisse décider, et où je reprends la main.
Préparation à la discussion d'entretien (cf. section 7 du brief). Le ton et les typos sont conservés — c'est l'envers du décor, pas une vitrine.
docs/personal_notes/call_path_creation_process.md— le brainstorm initial, ce que j'ai gardé / écarté, le cheminement vers la version livrée.docs/personal_notes/personal_feedback_and_thoughts.md— rétrospective : ce dont je suis content, ce que j'aimerais apporter, et ce que je sais sur l'état du code aujourd'hui.


