Matching instantané
Voir aussi : Reservation Admin — réservation par un admin (30 min), même affichage rouge. Modèle de données : voir entities/instant_matching.md — tables
instant_matching_reservationetalgo_matching_trace.
Vue d'ensemble
Le matching instantané permet de réserver un jeune + 3 bénévoles ensemble pendant 15 minutes. Pendant ce temps, ces 4 profils ne sont matchables par personne (ni admin, ni autre jeune). Le jeune dispose de 15 minutes pour choisir un des 3 mentors proposés ; sa sélection déclenche la création du binôme.
| Critère | Valeur |
|---|---|
| Acteur | Système (automatique, pas d'admin) |
| Granularité | 1 groupe = 1 jeune + 3 bénévoles |
| Durée | 15 minutes |
| Libération | Sélection du jeune → createBinomeInstant() ou expiration |
Microservice de matching
Le service MatchingAlgoService appelle un microservice externe pour le matching personnalisé.
Body envoyé au microservice
Chaque champ est construit à partir de la table jeune ou de jeune_extrait_precisions. Aucune valeur de repli : si la source est vide, on envoie '' (string) ou [] (array).
| Champ | Source | Cas vide |
|---|---|---|
jeune_programme |
jeune.programme |
'' |
jeune_cursus_actuel_ou_passe_cf |
jeune.school_cursus |
'' |
jeune_cursus_actuel_ou_passe_llm |
jeune_extrait_precisions.cursus_actuel_ou_passe_1/2 |
[] |
jeune_cursus_vise_llm |
jeune_extrait_precisions.cursus_vise_1/2/3 |
[] |
jeune_filiere_actuelle_ou_passee_cf |
jeune.filieres (array) |
[] |
jeune_filiere_actuelle_ou_passee_llm |
jeune_extrait_precisions.filiere_actuelle_ou_passee_1/2 |
[] |
jeune_filiere_visee_llm |
jeune_extrait_precisions.filiere_visee_1/2/3 |
[] |
jeune_secteur_vise_cf |
jeune.sectors (JSON array) |
[] |
jeune_secteur_vise_llm |
jeune_extrait_precisions.secteur_vise_X_1/2 (niveau1/niveau2) |
[] |
jeune_profession_visee_llm |
jeune_extrait_precisions.profession_visee_X_1/2 (niveau1/niveau2) |
[] |
jeune_poste_vise_llm |
jeune_extrait_precisions.poste_vise_1/2/3 (concaténés par ,) |
'' |
jeune_besoin |
jeune_extrait_precisions.objectif_1 puis fallback mapJeuneBesoin(jeune) |
Voir ci-dessous |
reponse_recepteur |
Paramètre d'appel (back_office ou front_jeune) |
— |
reponse_longueur |
Constante | 30 |
Format niveau1 / niveau2 : tableaux d'objets { niveau1: string, niveau2: string }, jusqu'à 3 paires par champ. Exemple :
"jeune_secteur_vise_llm": [
{ "niveau1": "Santé / Social / Environnement", "niveau2": "Santé" },
{ "niveau1": "Santé / Social / Environnement", "niveau2": "Social" }
]
jeune_besoin : si objectif_1 est renseigné, on l'envoie. Sinon, mapJeuneBesoin(jeune) dérive depuis jeune.besoins : slug study → "Atteindre un objectif d'études" (subs orienter/resultats/concours) ou "Définir mon projet d'études" ; slug pro → "Atteindre un objectif d'insertion pro" (subs candidate/interview/seek) ou "Définir mon projet pro" ; autre → BESOINS_MAP[slug] ou "Définir mon projet d'études".
Code : back/src/binomes/services/matching-algo.service.ts (buildRequestBody, epToLegacyFormat, mapJeuneBesoin).
Méthodes
| Méthode | Usage | Description |
|---|---|---|
getPersonnalizedBenevoles(jeune, adminId, reponseRecepteur) |
BO (algo=new), propose back_office | Top 50 bénévoles par compatibilité, liste plate |
getPersonnalizedBenevolesOnePerCategory(jeune, adminId, excludeIds?) |
propose front_jeune, refresh | 1 bénévole matchable par catégorie (femmes, non_femmes, generalistes, puis autres clés alpha). La clé est stockée sur la réservation (type_mentor). |
Catégories du microservice
La réponse contient des clés : femmes, non_femmes, generalistes. Pour le matching instantané côté jeune, on prend le premier disponible de chaque catégorie, puis on mélange l'ordre.
Fallback microservice indisponible
Si le microservice est inaccessible (timeout 30 s, erreur réseau ou HTTP) :
getPersonnalizedBenevolesOnePerCategory: 1 tentative sans retry → retourne[]getPersonnalizedBenevoles: 1 tentative + 1 retry (même timeout 30 s) → retourne[]
Dans les deux cas, le service bascule sur le fallback local via getTopBenevolesForJeune(jeune, 3) :
- Charge tous les bénévoles matchables depuis la DB locale (
loadMatchableBenevoles) - Calcule un score de rating classique (
ratingService.calculateBinomeRating) pour chacun - Exclut les bénévoles avec score
-99(disqualifiés) - Retourne les top 3 par score décroissant
Les mentors proposés ne sont pas aléatoires — c'est un classement déterministe par score. Le champ type_mentor est NULL sur les réservations créées via ce fallback (pas de catégorie femmes/non_femmes/generalistes).
Ce fallback s'applique aussi au refresh quand au moins un bénévole est devenu indisponible.
Logs
Appels logués avec préfixe [matching-algo] : body envoyé, réponse brute, mentors parsés, bénévoles exclus, résultat final. En cas d'erreur (ex. 500), le body est inclus dans le log.
Logique métier
Durée : 15 minutes
Une réservation est active si :
deletedAt IS NULL AND reservationDate + 15 minutes > NOW()
Expiration
Aucune action automatique (pas de cron). Les réservations expirées restent en base et sont ignorées via le filtrage à la lecture.
Profil non matchable
Un jeune ou un bénévole est non matchable si :
1. Il a une AdminReservation active (30 min), OU
2. Il apparaît dans une InstantMatchingReservation active (15 min)
Les deux systèmes se cumulent.
Implémentation backend
- postBinome (BinomeController) : Bloque la création si le jeune ou le bénévole est en matching instantané actif.
- Listes de matching (RatingController) :
jeuneListetbenevoleListexcluent les profils en matching instantané actif. - Listes BO (JeuneRepository, BenevoleRepository) :
findAndFilterexclut les jeunes et bénévoles en matching instantané actif.
Affichage frontend (BO)
L'affichage du matching instantané réutilise celui de la réservation admin :
Condition de masquage du bouton Matcher :
!(item.resa || item.instantMatchingResa)
Choix de l'algorithme de matching (jeunes uniquement)
Pour les jeunes, le bouton "Matcher" est un menu déroulant proposant 2 choix :
| Choix | Label | Route |
|---|---|---|
| 1 | Nouvel algo - bêta | /bo/jeunes/:id/matching?algo=new |
| 2 | Algo classique | /bo/jeunes/:id/matching?algo=classic |
Disponibilité du nouvel algo
| Contexte | Nouvel algo disponible |
|---|---|
| Jeunes (proposer des bénévoles à un jeune) | ✅ Tous les admins (admin + superadmin) |
| Bénévoles (proposer des jeunes à un bénévole) | ❌ Non — bouton simple, algo classique uniquement |
L'endpoint GET /rating/benevoleList/:jeuneId accepte ?algo=new (appel microservice). GET /rating/jeuneList/:benevoleId utilise toujours l'algo classique.
Option admin « Matching instant »
| Élément | Détail |
|---|---|
| Stockage | administrator.options.options.matching_instant |
| Édition | Page BO /bo/admin/cs/:id/edit — case à cocher |
| Liste admins | Colonne + filtre checkbox sur /bo/admin/cs |
| API | GET /admin/role/all?filterMatchingInstant=true ; filtre via JSON_EXTRACT(options, '$.options.matching_instant') |
| Valeur par défaut | matching_instant: false à la création du rôle |
Assignation d'un admin à la création du binôme instantané
Lors de createBinomeInstant, un admin de suivi est sélectionné :
| Règle | Détail |
|---|---|
| Critères | Admins de la région du jeune (schoolRegion), matching_instant: true, profil admin ou superadmin, sandbox compatible |
| Choix | Aléatoire parmi les éligibles (pickRandomAdminForInstantMatching) |
| Si aucun | adminId = null ; binôme créé quand même |
| Assignation | binome.adminId, jeune.adminId, benevole.adminAssocieId |
Bénévoles éligibles : sans admin associé
| Contexte | Vérification |
|---|---|
| Microservice | checkBenevoleDisponible : si adminId === '__instant_matching__' et benevole.adminAssocieId != null → exclu |
| Fallback local | loadMatchableBenevoles : filtre benevole.adminAssocieId != null → exclu |
La page /bo/jeunes/:id/matching affiche un v-chip indiquant l'algorithme actif (?algo=new → "Nouvel algo -
bêta", sinon "Algo classique").
Type de binôme et traçabilité
| Parcours | Service | binome.type |
|---|---|---|
| Jeune — validation réservation 15 min | InstantMatchingService.validate → createBinomeInstant() |
instant |
| Back-office — admin avec option matching instantané | BinomeController.postBinome → createBinome() |
manuel |
binome.type
| Valeur | Description |
|---|---|
manuel |
Créé via createBinome() (défaut BO, y compris matching instantané admin) |
auto |
Alternatif via createBinome() (double proposition multiproposition) |
instant |
Uniquement createBinomeInstant() (matching instantané jeune) |
binome.typeAlgo
Indique si le score vient du nouvel algo (v2) ou du rating classique (classic). v2 si la réservation porte un score microservice, classic si score legacy.
Commentaire automatique sur le binôme
- Parcours jeune (
validate→createBinomeInstant) :Matching instantané - nouvel algo - {DD/MM/YYYY}(score v2) ouMatching instantané - algo classique - {DD/MM/YYYY}(score legacy) - Parcours BO (
postBinomeavecisInstantMatching) : texte basé sur le query paramalgo
Filtre "Matching" sur la liste des binômes
| Valeur | Label | Types inclus |
|---|---|---|
instantane |
Instantané | type = 'instant' |
manuel |
Manuel | type IN ('manuel', 'auto') |
Indicateur visuel "déjà proposé en matching instantané"
Sur les pages de matching (BO), si un profil a déjà été dans une réservation avec le profil en cours (même expirée/terminée) :
- Page liste (
/matching/index.vue) : fond grisé sur la card du profil déjà proposé - Page confirmation (
/matching/:id) : message gris "{Prénom mentor} a déjà été proposé à {Prénom jeune} lors du matching instantané"
Le contrôle porte sur toutes les réservations passées (y compris expirées et soft-deleted).
Endpoints backend associés
GET /rating/benevoleList/:jeuneId: chaque bénévole enrichi d'un flagwasProposedInInstantMatching: booleanGET /rating/jeuneList/:benevoleId: idem pour les jeunesGET /rating/wasPreviouslyProposed?jeuneId=X&benevoleId=Y→{ wasProposed: boolean }— appelé directement par les pages de confirmation (pas via query param, pour éviter la falsification par URL)
Endpoints API (côté jeune)
| # | Méthode | Route | Description |
|---|---|---|---|
| 1 | POST | /instant-matching/propose |
Proposer 3 bénévoles |
| 2 | POST | /instant-matching/refresh |
Renouveler les 3 bénévoles réservés |
| 3 | POST | /instant-matching/confirm-selection |
Confirmer le choix (états : sélectionné / autre selectionné) |
| 4 | POST | /instant-matching/validate |
Valider et créer le binôme |
| 5 | POST | /instant-matching/refuse |
Refuser les 3 bénévoles |
| 6 | POST | /instant-matching/cancel |
Annuler et passer en non disponible |
Architecture : InstantMatchingController — auth (JwtAuthGuard) + vérification propriété (getAuthenticatedJeune) + délégation à InstantMatchingService.
Collection Bruno : back/bruno/instant-matching/.
Mise en forme des bénévoles proposés
Quand : Fin d'inscription du jeune (après finishInscriptionJeune, jeune APTE). Également à chaque chargement de la page de sélection.
Entrée : { jeuneId: string }
Comportement idempotent :
| Situation | Comportement | expired |
|---|---|---|
| Aucune réservation | Crée 3 réservations, renvoie les bénévoles | false |
| Réservations actives (< 15 min) | Renvoie les mêmes sans toucher au timer | false |
| Réservations expirées (> 15 min, non supprimées) | Renvoie les mêmes sans toucher au timer | true |
| Réservations soft-deleted | Erreur 400 — propositions déjà faites | — |
Logique (première fois, contexte front_jeune) :
1. Vérifier jeune existant, req.user propriétaire, état APTE et Autonome
2. Vérifier via findCurrentForJeune — si réservations existantes, les renvoyer avec flag expired
3. Appel microservice getPersonnalizedBenevolesOnePerCategory() — 1 bénévole matchable par catégorie ; si microservice indisponible → fallback local top 3 par rating classique (type_mentor = NULL)
4. Mélange aléatoire en préservant la paire (bénévole + type_mentor)
5. Créer 3 lignes InstantMatchingReservation avec orderIndex 0/1/2, etat: 'proposé', score, type_mentor
6. Retourner les 3 bénévoles avec expired: false
Contexte back_office : top 3 via getTopBenevolesForJeune() ; type_mentor = NULL.
Sortie :
{
success: boolean;
expired: boolean;
expiresAt?: string;
reservations: {
benevoleId: string;
firstName: string;
lastName: string;
etat: 'proposé' | 'sélectionné' | 'autre selectionné' | 'refusé' | 'desactivation';
rating: number;
ratingDetails: string;
department: string;
region: string;
secteurs: string[];
postes: string[];
cursus: string[];
filieres: string[];
diplomes: string[];
experience: string;
passions: string;
alternance: boolean;
}[];
}
Cas particuliers :
- Moins de 3 bénévoles disponibles : retourner ce qui est disponible, ou success: false si aucun
- Réservations soft-deleted → erreur 400 "Le matching instantané a déjà été proposé."
Endpoint 2 : POST /instant-matching/refresh
Quand : Jeune revient sur la page (rechargement, retour, timer proche de l'expiration).
Entrée : { jeuneId: string }
Logique :
1. Vérifier jeune + ownership
2. Récupérer réservations non-supprimées via findCurrentForJeune
3. Si aucune → { success: true, reservations: null }
4. Vérifier disponibilité de chaque bénévole : pas MATCHE (sauf multibinome), Autonome, pas de réservation admin active, pas de réservation instant matching pour un autre jeune
5. Tous disponibles : 3 nouvelles lignes avec mêmes score / type_mentor
6. Au moins un indisponible : appel microservice getPersonnalizedBenevolesOnePerCategory() pour 3 nouveaux (fallback getTopBenevolesForJeune() si microservice indisponible → type_mentor = NULL)
7. Soft-delete anciennes réservations, créer 3 nouvelles (historique conservé)
Sortie :
{
success: boolean;
reservations: { ... }[] | null;
}
Endpoint 3 : POST /instant-matching/confirm-selection
Quand : Le jeune clique sur "Confirmer mon choix".
Entrée : { jeuneId: string, benevoleId: string }
Logique :
1. Vérifier jeune + ownership
2. Vérifier que le bénévole fait partie des réservations actuelles
3. updateEtatForValidate(jeuneId, benevoleId) — sélectionné → sélectionné, autres → autre selectionné
4. Pas de soft-delete, pas de création de binôme
Sortie : { success: boolean }
Erreur : bénévole non trouvé dans les réservations → 400
Endpoint 4 : POST /instant-matching/validate
Quand : Le jeune clique sur "Envoyer et valider le binôme".
Entrée : { jeuneId: string, benevoleId: string, firstMessageJeune?: string }
firstMessageJeune = concaténation des 3 champs du formulaire (présentation, objectifs, dispos) séparés par \n.
Logique :
1. Vérifier jeune + ownership
2. Vérifier que le bénévole est dans les réservations actives
3. Validations de sécurité : jeune pas déjà MATCHE, jeune et bénévole Autonome, bénévole non-multibinome pas MATCHE, limites binômes, onlyOneBinome, PNP/partenaire, PNP/VIP, même sandbox
4. updateEtatForValidate(jeuneId, benevoleId, true) — sélectionné → matché, autres → autre selectionné
5. Soft-delete des 3 réservations
6. createBinomeInstant() : type = instant, typeAlgo = v2/classic, status EN_ATTENTE, firstMessageJeune stocké
7. Mails : événement instant.binome.created → instant.benevole-0 et instant.jeune-0 ; lastStepDone=0, nextStepDate = +15 jours
8. Statuts : jeune → MATCHE, bénévole → MATCHE
9. Commentaire automatique sur le binôme
10. Si sandbox MVLS : mvlsService.publishBinomeMessage
11. Si sandbox non-MVLS : création des todo lists (besoins sans slug valide ignorés)
Sortie : { success: boolean, binomeId: string }
Erreurs :
- Bénévole non trouvé dans les réservations actives → 400
- Bénévole plus disponible / multibinome max atteint / onlyOneBinome → 409 Conflict
- Jeune déjà matché, non autonome, PNP+partenaire/VIP, sandbox différente → 400
Endpoint 5 : POST /instant-matching/refuse
Quand : Le jeune ne souhaite aucun des 3 bénévoles.
Entrée : { jeuneId: string }
Logique :
1. Vérifier jeune + ownership
2. updateEtatForJeune(jeuneId, 'refusé')
3. Soft-delete via softDeleteAllCurrentForJeune
4. Commentaire individuel : "Matching instantané refusé" (adminId: null)
5. Le jeune reste APTE
Sortie : { success: boolean }
Endpoint 6 : POST /instant-matching/cancel
Quand : Le jeune annule et ne veut plus être disponible.
Entrée : { jeuneId: string }
Logique :
1. Vérifier jeune + ownership
2. updateEtatForJeune(jeuneId, 'desactivation')
3. Soft-delete via softDeleteAllCurrentForJeune
4. Commentaire individuel : "Matching instantané - désactivation"
5. changeStatusJeune(jeuneId, 'NON_DISPONIBLE', 'MATCHING_INSTANTANE') + logs
Sortie : { success: boolean }
Mise en forme des bénévoles proposés (formatBenevoleResponse)
formatBenevoleResponse (instant-matching.service.ts) transforme un Benevole avec ses relations en objet plat pour l'affichage côté jeune. Fusionne données CF (champ fermé) et LLM (BenevoleExtraitPrecision).
Sources de données
| Champ | Sources CF | Sources LLM | Déduplication |
|---|---|---|---|
| secteurs | Benevole.secteurMetier + PosteBenevole[].secteur |
extraitPrecision.secteurXX (paires niveau1/niveau2) |
Taxonomique via taxonomie_secteurs_professions.json |
| postes | PosteBenevole[].poste (courant en premier) |
extraitPrecision.poste1/2/3 |
Case-insensitive |
| cursus | CursusBenevole[].cursus ("Autre" → cursusAutre) |
extraitPrecision.cursus1/2 |
Case-insensitive |
| filieres | CursusBenevole[].filiere ("Autre" → filiereAutre) |
extraitPrecision.filiere1/2 |
Case-insensitive |
| diplomes | CursusBenevole[].diplome |
— | Aucune |
Déduplication des secteurs
- Valeurs CF depuis
Benevole.secteurMetier+PosteBenevole[].secteur(déduplication case-insensitive) - Chaque valeur CF traduite en
{ niveau1, niveau2 }viataxonomie_secteurs_professions.json(comparaison uniquement, jamais pour affichage) - Si la traduction correspond à une entrée LLM → l'entrée LLM est "couverte", on affiche la valeur CF d'origine
- Entrées LLM non couvertes affichées par niveau1 uniquement
- Ordre : valeurs CF d'abord, puis niveau1 LLM non couverts
Fichiers : back/src/binomes/utils/merge-secteurs.ts (mergeSecteurs, mergePostes, mergeCursus, mergeFilieres) ; back/src/binomes/imports-files/taxonomie_secteurs_professions.json.
Les champs sont affichés en chips dans front/pages/compte/jeune/mentors/MentorCard.vue.
Flux fonctionnel
Création de la réservation
- Jeune termine l'inscription →
POST /instant-matching/propose - Sélection des 3 bénévoles : microservice (1 par catégorie) ou fallback local avec
calculateBinomeRating - Création de 3 lignes
InstantMatchingReservationavectype_mentor= clémentorsouNULL(fallback/BO) - Affichage des 3 bénévoles au jeune
Pendant 15 minutes
- Jeune et 3 bénévoles visibles dans les listes BO mais exclus de
findMatchable - Bouton Matcher masqué, icône "i" rouge
- Recharge page →
/proposerenvoie les mêmes 3 bénévoles sans toucher au timer (expired: false)
Après expiration (> 15 min)
- Profils redeviennent matchables dans les listes BO
/proposerenvoie les mêmes 3 avecexpired: true- Le front appelle
/refreshpour renouveler et remplacer les indisponibles
Affichage selon l'état (page /compte/jeune/mentors)
| État des réservations | Affichage |
|---|---|
| Tous en "proposé" | 3 cartes mentors, titre "Choisis ton mentor", bouton "Confirmer mon choix" |
| Un en "sélectionné" | Vue directe "Mentor choisi: {Prénom}", formulaire message, bouton "Envoyer et valider le binôme" |
Flux :
1. propose/refresh → réservations avec champ etat
2. etat === 'sélectionné' → picked défini, affichage formulaire
3. Clic "Confirmer" → POST /instant-matching/confirm-selection
4. Clic "Valider" → POST /instant-matching/validate
Libération
| Cas | Action |
|---|---|
| Validation | validate → sécurité, binôme type: 'instant', statuts MATCHE, soft-delete, commentaire, TodoLists (sauf MVLS), RabbitMQ (si MVLS) |
| Refus | refuse → soft-delete, commentaire "refusé", jeune reste APTE |
| Annulation | cancel → soft-delete, commentaire "désactivation", jeune NON_DISPONIBLE |
| Expiration | Profils redeviennent matchables BO ; réservations conservées ; /propose → expired: true |
Création du binôme : createBinomeInstant
Fonction dédiée (pas createBinome) avec les spécificités suivantes :
| Paramètre | Valeur |
|---|---|
type |
Toujours instant |
typeAlgo |
v2 si réservation avec score microservice ; classic si score legacy |
status |
Directement EN_ATTENTE (pas de phase EN_ATTENTE_JEUNE, pas de premerBinome) |
firstMessageJeune |
Texte du formulaire (présentation / objectifs / dispos, séparés par \n) |
lastStepDone |
0 |
nextStepDate |
Création + 15 jours |
Admin : aléatoire (région du jeune + matching_instant: true) ; null si aucun éligible.
Mails (événement instant.binome.created) :
- instant.benevole-0 (Brevo #3955) : PRENOM, PRENOM_admin, PRENOM_JEUNE, schoolCursus, filiereJeune, texte_matching
- instant.jeune-0 : PRENOM, PRENOM_admin, PRENOM_mentor
Comportements spécifiques
Popup d'expiration côté jeune
Quand le timer expire sur /compte/jeune/mentors :
1. Popup : souhait de renouveler la réservation
2. "Mettre à jour" → POST /instant-matching/refresh
3. Si le jeune recharge avec une réservation expirée, la popup s'affiche immédiatement
Protections back-office
| Protection | Composant | Comportement |
|---|---|---|
| Bouton "Matcher" désactivé | ButtonsAdmin.vue |
Désactivé si isInInstantMatching (tous rôles y compris superadmin) |
| Message d'erreur | MatchingErrorMessages.vue |
"Ce jeune/bénévole est réservé pour un Matching Instantané..." |
| Icône "i" rouge | IDataTable.vue, ITableView.vue |
Si instantMatchingResa actif |
| Protection backend | postBinome |
Bloque si jeune ou bénévole en matching instantané actif |
Conditions de disponibilité lors d'un refresh
Un bénévole est maintenu si :
- status === 'APTE' OU (status === 'MATCHE' ET multibinome ET activeBinomeCount < 2)
- state === 'Autonome'
- Pas de réservation admin active
- Pas de réservation instant matching pour un autre jeune
Régions éligibles au matching instantané
Constante INSTANT_MATCHING_REGIONS (front/constants/reservation.js) :
['Île-de-France', 'Grand Est', 'Bourgogne-Franche-Comté']
| Comportement | Condition |
|---|---|
| Champ "about" masqué à l'onboarding | schoolRegion dans INSTANT_MATCHING_REGIONS |
Le champ "about" reste visible dans la page profil et en back-office.
Modifications de l'onboarding jeune
Étape "Situation" (id: 43)
| Élément | Valeur |
|---|---|
| Titre de l'étape | "Aide nous à te trouver le mentor idéal pour ta situation" |
| Titre du mood | "Comment te sens-tu en ce moment ?" |
| Titre du champ precision | "Décris ta situation" |
| Subtitle du champ precision | "Tes études, ton projet pour la suite, les difficultés que tu rencontres" |
| Champ precision | Obligatoire, 50 caractères minimum (compteur affiché) |
Carrousel d'aide
Le composant HelpCarousel (front/components/inscription/widgets/v2/helpCarousel.vue) remplace le panneau statique. Header : "Besoin d'aide pour remplir ce champ ?", 3 exemples en carrousel.
Comparaison avec AdminReservation
| Critère | AdminReservation | InstantMatchingReservation |
|---|---|---|
| Acteur | Admin | Système |
| Granularité | 1 admin ↔ 1 jeune OU 1 bénévole | 1 jeune + 3 bénévoles |
| Durée | 30 min | 15 min |
| Libération | Bouton admin ou expiration | Sélection jeune ou expiration |
| Affichage | Rouge | Rouge (identique) |
Constantes et utilitaires
| Fichier | Contenu |
|---|---|
back/src/binomes/constants/reservation.constants.ts |
Durées (15 min, 30 min), conditions SQL réutilisables |
back/src/binomes/utils/reservation-load.utils.ts |
needsFilteredReservations, relationsWithoutReservations |
front/constants/reservation.js |
ADMIN_RESERVATION_MS, INSTANT_MATCHING_RESERVATION_MS, isInstantMatchingActive(), INSTANT_MATCHING_REGIONS |