npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@amsom-habitat/cresol

v0.2.8

Published

Création de sollicitation (assistant 3 étapes) réutilisable par les outils AMSOM Habitat

Readme

Cresol

Assistant de création de sollicitation, extrait de Cally2 et réutilisable par les outils AMSOM Habitat.

L'assistant est autonome : il charge lui-même la nomenclature, l'arbre patrimonial et les collaborateurs, puis poste la création et les documents joints. Il ne connaît rien de l'outil qui l'héberge. Celui-ci lui donne :

  • les réclamants possibles (le dossier consulté) ;
  • éventuellement un brouillon pré-alimenté et des champs figés ;
  • le contenu des volets latéraux (sollicitations similaires, évènements), qui restent les siens.

En retour, il reçoit des événements à chaque moment clé : avant et après la création, et aux changements de réclamant, de motif et d'étape.

┌──────────────── outil hôte ────────────────┐
│  props : reclamants, modelValue, readonly… │
│  slots : volets similaires / évènements    │
└───────────────┬────────────────▲───────────┘
                │                │ événements : beforeCreate, created,
                ▼                │ createError, motifChange…
        ┌──────────────── Cresol ────────────────┐
        │ [Réclamant] › Catégorisation › Cible › │
        │ Détails  →  POST création + documents  │
        └────────────────────────────────────────┘

Sommaire

Installation

npm i @amsom-habitat/cresol

Pas de feuille de style à importer : le CSS est injecté par le JS du paquet. L'outil fournit, lui, Bootstrap (@amsom-habitat/bootstrap-5) et le composant global font-awesome-icon. Les icônes sont l'affaire du paquet : celles de son interface sont enregistrées au chargement (src/icons.js), celles portées par les données (motifs, catégories…) à la volée.

Configuration

À poser une fois au démarrage de l'outil :

import { configureCresol } from '@amsom-habitat/cresol'

configureCresol({ baseUrl: import.meta.env.VITE_API_URL })

| Option | Défaut (@amsom-habitat/user-manager) | Rôle | | --------------- | -------------------------------------- | ----------------------------------- | | baseUrl | — (obligatoire) | Racine de l'API métier | | getToken | cookie partagé du domaine | Jeton envoyé à chaque appel | | setToken | écrit le cookie | Jeton renouvelé (refresh 449) | | logout | déconnexion du domaine | Refresh impossible | | goToLoginPage | page de login du domaine | 401 / 498 sur un appel qui redirige |

Un outil du domaine ne pose que baseUrl : le jeton suit le SSO. Les autres options servent à un outil qui gère son authentification lui-même.

La prop baseUrl surcharge l'API pour une instance (prop › configureCresol › défaut) : storybook, démo, seconde API. Le jeton, lui, ne passe que par configureCresol : un getToken / setToken couplés est ce qui permet au refresh 449 de rejouer la requête, et le logout est celui de l'outil (pas de déconnexion SSO décidée par le paquet). Sans baseUrl nulle part, l'appel échoue avec une erreur explicite plutôt que de partir en relatif sur l'origine de la page.

Démarrage rapide

<template>
  <creer-sollicitation-modal
    v-if="open"
    :reclamants="[{ type: 'L', id: 2200523, libelle: 'Contrat' }]"
    :model-value="{ provenance: 'T' }"
    :readonly="['reclamant']"
    @created="onCreated"
    @error="$toast.error($event)"
    @close="open = false"
  >
    <template #aside-similaires="{ idMotif, codeProgramme, idCible }">
      <mes-similaires :id-motif="idMotif" :code-programme="codeProgramme" :id-cible="idCible" />
    </template>
    <template #aside-evenements>
      <mes-evenements-de-patrimoine />
    </template>
  </creer-sollicitation-modal>
</template>

<script>
import { CreerSollicitationModal } from '@amsom-habitat/cresol'

export default {
  components: { CreerSollicitationModal },
  data: () => ({ open: true }),
  methods: {
    onCreated(sollicitations) {
      this.$toast.success(`${sollicitations.length} sollicitation(s) créée(s)`)
      // … recharger le listing de l'outil
    }
  }
}
</script>

Deux composants, même contrat (props, événements, slots, définis une seule fois dans src/props.js) :

  • CreerSollicitationForm : l'assistant seul, à placer dans une page ou dans sa propre modale ;
  • CreerSollicitationModal : le même, dans une AmsomModal. Il ajoute les props titre (défaut 'Nouvelle sollicitation') et closeOnCreated (défaut true : émet close juste après created), et l'événement close (croix, ou création réussie). Ses attributs non déclarés (reducible, title…) descendent sur AmsomModal.

Props

| Prop | Type | Défaut | Rôle | | ---------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------------------------- | | reclamants | Array | [] | Réclamants proposables : [{ type, id, libelle }] (détail) | | reclamantMode | String | 'select' | Présentation du choix : select, switch, autocomplete, step | | typesReclamant | Array | null | Codes KRCLENT.RCLT cherchables en mode step (null = tous) (détail) | | typesReclamantExclus | Array | [] | Codes KRCLENT.RCLT retirés de la recherche en mode step | | provenances | Array | 6 canaux | Codes KRCLENT.CTRANS proposés, dans cet ordre (null = toutes les actives) (détail) | | provenancesExclues | Array | [] | Codes KRCLENT.CTRANS retirés des provenances proposées | | modelValue | Object | null | Brouillon pré-alimenté, partiel ; suivi en v-model (détail) | | readonly | Boolean | Array | false | Champs figés : true, false ou une liste (détail) | | modules | Array | null | Modules du réclamant ; laissés null, chargés pour un réclamant contrat | | idModule | String | Number | null | Module à préférer comme cible par défaut parmi ceux du réclamant | | nomenclatureFilter | Function | null | Prédicat : quels motifs sont proposables (détail) | | aside | Boolean | true | Affiche le volet latéral (ses onglets viennent des slots) | | nbSimilaires | Number | 0 | Badge de l'onglet « Similarité » | | baseUrl | String | null | API de cette instance (sinon configureCresol) |

Chaque prop porte une seule responsabilité. Les valeurs de la saisie passent par modelValue, les choix possibles par reclamants, ce qui est modifiable par readonly, et la présentation du réclamant par reclamantMode. Il n'y a donc pas de prop provenance : on la passe dans modelValue ({ provenance: 'M' }) ; provenances ne dit que lesquelles proposer.

Les provenances

Libellés et activité viennent de la table krclorig (vue AHVWS_SOLLICITATION_PROVENANCE, GET /v2/sollicitation/provenances?estDesactive=false) : une provenance inactive n'est jamais proposée, sans rien changer dans l'outil. Le paquet ne porte que les icônes (PROVENANCE_CONTACT_ICONS, repli comment-dots).

Comme pour typesReclamant, l'outil choisit lesquelles proposer : provenances (liste blanche, qui fixe aussi l'ordre) puis provenancesExclues (liste noire). Par défaut, les six canaux saisis par un agent (PROVENANCES_CONTACT_DEFAUT : T, M, G, V, IP, C) ; null propose toute la table, canaux automatiques compris (Volly, Link…). Une provenance pré-remplie (modelValue) qui n'est pas proposée — exclue ou devenue inactive — bloque l'étape, comme une provenance vide.

<!-- accueil physique -->
<creer-sollicitation-form :provenances="['V', 'C', 'T']" />
<!-- toute la table sauf Volly et Link -->
<creer-sollicitation-form :provenances="null" :provenances-exclues="['VO', 'LI']" />

modelValue n'est lu qu'à l'ouverture : le modifier ensuite ne réinitialise pas l'assistant. Pour repartir d'un autre brouillon, on remonte le composant (v-if ou :key).

Événements

| Événement | Quand | Charge utile | | ------------------- | ----------------------------------------- | ------------------------------------------------------------ | | update:modelValue | à chaque modification du brouillon | le brouillon | | reclamantChange | l'utilisateur change de réclamant | l'entrée de reclamants choisie | | motifChange | le motif ou les motifs associés changent | { idCategorie, idType, idNature, idMotif, motifsAssocies } | | stepChange | changement d'étape | { step, key, previous: { step, key } } | | beforeCreate | clic sur « Créer », avant l'appel API | { payload, cancel, waitUntil } | | created | création réussie (documents compris) | (sollicitations, { payload, fichiers }) | | createError | l'API a refusé la création | { error, message, payload } | | error | toute erreur affichable | message (chaîne) | | close | (modale) fermeture demandée | — |

reclamantChange, motifChange et stepChange ne sont pas émis pour l'état initial : l'outil le connaît déjà, puisque c'est lui qui l'a fourni. Ils rendent compte de ce que fait l'utilisateur.

Le cycle de la création

clic « Créer »
   │
   ├─ beforeCreate ── cancel() / waitUntil(false | rejet) ──▶ rien n'est envoyé, l'assistant reste ouvert
   │
   ├─ POST creer_sollicitation ── échec ──▶ createError + error, l'assistant reste ouvert
   │
   ├─ POST upload_sollicitation_ged (un par document, en parallèle)
   │      échec d'un document ──▶ error (la création, elle, est acquise)
   │
   └─ created(sollicitations, { payload, fichiers })   (modale : puis close)

Pendant tout le cycle, l'assistant est sous overlay et un second clic est ignoré.

Succès et échec sont séparés (created / createError) : l'outil n'y fait pas la même chose (fermer et recharger d'un côté, garder la saisie et expliquer de l'autre), et chacun porte une charge utile différente. error reste le canal unique des messages pour qui ne veut que toaster : il reçoit aussi les échecs de création, ceux des documents et ceux des chargements. Règle simple :

  • pour afficher une erreur, écouter error ;
  • pour réagir à l'échec de la création (journaliser, proposer autre chose…), écouter createError.

beforeCreate : intervenir avant l'envoi

L'événement porte un objet :

| Clé | Rôle | | -------------------- | ------------------------------------------------------------------------------ | | payload | le corps qui va partir (forme) ; modifiable en place | | cancel() | annule la création | | waitUntil(promise) | fait attendre l'envoi ; résolue à false, ou rejetée, elle annule la création |

// Confirmation
onBeforeCreate({ payload, waitUntil }) {
  waitUntil(this.$confirm(`Créer ${payload.lignes.length} sollicitation(s) ?`))
}

// Veto synchrone
onBeforeCreate({ payload, cancel }) {
  if (!this.peutCreer(payload)) cancel()
}

// Enrichir le payload
onBeforeCreate({ payload }) {
  payload.lignes.forEach((ligne) => (ligne.description += `\n[${this.origine}]`))
}

Une annulation est silencieuse : rien n'est émis ensuite. C'est l'outil qui l'a décidée, il sait déjà pourquoi.

created : le compte rendu

onCreated(sollicitations, { payload, fichiers }) {
  // sollicitations : une par ligne, sérialisées par l'API ([{ id, idMotif, … }])
  // fichiers       : un compte rendu par document joint
  //   [{ idMotif, nom, idSollicitation, ok: true | false, message }]
  const enEchec = fichiers.filter((f) => !f.ok)
}

Un document en échec n'annule pas la création : il est signalé par error et marqué ok: false, et l'utilisateur pourra le joindre depuis le détail de la sollicitation.

Les autres événements

// Recharger ce qui dépend du réclamant (sollicitations similaires, évènements…)
onReclamantChange(reclamant) {}

// Suggestions, alertes métier propres à l'outil sur un motif
onMotifChange({ idMotif, motifsAssocies }) {}

// Suivi d'usage, aide contextuelle par étape
onStepChange({ key, previous }) {}   // key : 'reclamant' | 'categorie' | 'cible' | 'details'

Slots

| Slot | Contenu | Absent ⇒ | | ------------------ | ----------------------------------------------- | --------------- | | aside-similaires | onglet « Similarité » ; scopé (voir ci-dessous) | pas d'onglet | | aside-evenements | onglet « Événements » | pas d'onglet | | aside | remplace tout le volet latéral | volet à onglets | | reclamant | (mode step) remplace l'étape réclamant | recherche |

Les deux volets appartiennent à l'outil : c'est lui qui interroge son API et rend ses cartes. Le paquet ne lui fournit que le scope de la saisie en cours :

| Clé du scope | Valeur | | --------------- | ----------------------------------------------------------------------- | | idMotif | motif de la ligne principale | | codeProgramme | programme de la localisation ciblée (nul quand la cible est la demande) | | idCible | id de la demande ciblée (nul sinon) | | reclamant | le réclamant sélectionné |

Le badge de l'onglet revient par la prop nbSimilaires.

Le choix du réclamant

reclamants est une liste ordonnée d'entrées { type, id, libelle } :

  • type est le code KRCLENT.RCLT : L / P = contrat (TYPES_RECLAMANT_CONTRAT), D = demande, U = individu « Autre », T = tiers, F = fournisseur, E = personnel ; un code inconnu n'est pas traité comme un contrat ;
  • libelle est ce qui est affiché (côté Cally : « Contrat », « Demande », « Partie externe ») ;
  • il n'y a pas de clé technique : un réclamant s'identifie par son couple type + id.

Le premier de la liste est sélectionné, sauf si modelValue.reclamant ({ type, id }) en désigne un autre. Le type choisi pilote la suite :

| Réclamant | Cible proposée | | ------------------------- | ------------------------------------------------------------------------------ | | contrat | le contrat lui-même, sur l'un de ses modules (chargés si modules est null) | | demande (D) | toujours la demande, sans localisation | | partie externe (U, T) | une localisation du patrimoine (pas de contrat propre) |

Présentation, selon reclamantMode :

| reclamantMode | Rendu | | --------------- | --------------------------------------------------------------------- | | select | liste déroulante (défaut) | | switch | boutons côte à côte | | autocomplete | AmsomAutocomplete, pour une liste longue (recherche sur le libellé) | | step | une étape dédiée de recherche, avant la catégorisation |

Avec un seul réclamant, ou 'reclamant' dans readonly, il est seulement affiché (modes select, switch, autocomplete). Le mode step est à part : le réclamant y est cherché, reclamants et 'reclamant' dans readonly y sont ignorés ; seul modelValue.reclamant le présélectionne (cf. ci-dessous). Le stepper compte une étape de plus et stepChange émet key: 'reclamant'.

L'étape réclamant (step)

Par défaut, l'étape fait chercher le réclamant : on choisit d'abord Locataire, Demandeur, Tiers, Autre, Fournisseur, Personnel ou Tout (toutes les catégories proposées à la fois), puis on tape dans une barre de recherche (nom, prénom, n° de contrat ou de demande, adresse, téléphone, mail), comme la recherche de contrat de l'étape cible. Rien d'autre : pas de liste de l'outil à côté.

| Catégorie | Réclamant (type) | Ce qui est proposé | | ------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------- | | locataire | le contrat (L, P…) | signataires et occupants de contrats non archivés, sauf les occupants non signataires d'un contrat de personne morale | | demandeur | la demande (D) | signataires de demandes non archivées, actives ou modifiées depuis moins d'un an | | tiers | le tiers (T) | tiers valides | | autre | l'individu (U) | individus « Autre » | | fournisseur | le fournisseur (F) | fournisseurs valides de la société courante | | personnel | le collaborateur (E) | collaborateurs non invalidés | | tout | selon la ligne | les catégories proposées, mélangées ; chaque résultat porte sa categorie |

L'outil règle les réclamants proposés par code KRCLENT.RCLT (L, P, D, T, U, F, E — tous par défaut) ; une catégorie n'apparaît que si l'un de ses codes est autorisé, et les résultats sont filtrés par code (['L'] écarte les contrats P). Tout n'apparaît qu'à partir de deux catégories :

<!-- pas de fournisseurs -->
<creer-sollicitation-form reclamant-mode="step" :types-reclamant-exclus="['F']" />
<!-- fournisseurs et tiers uniquement -->
<creer-sollicitation-form reclamant-mode="step" :types-reclamant="['F', 'T']" />

Le réclamant est celui de Cally (KRCLENT.RCLT + RCLC) : le contrat, la demande, le tiers ou l'« Autre », jamais l'individu. La recherche porte sur les individus (noms, téléphones, mails des signataires, occupants, demandeurs), puis les résultats sont regroupés par réclamant : un contrat à deux signataires trouvés n'apparaît qu'une fois, avec les deux noms. Individus archivés exclus ; les contrats sortis et demandes inactives restent proposés, signalés et classés après les autres. Le réclamant trouvé est une entrée { type, id, libelle, categorie, libelleReclamant, adresse, estActif, individus } : c'est elle que reçoivent reclamantChange et le scope des volets. Ses modules sont chargés à la sélection (cible par défaut).

Un réclamant pré-alimenté par modelValue.reclamant ({ type, id }, ex. une duplication après création) est retrouvé par la recherche à l'ouverture, puis affiché comme s'il venait d'être choisi ; il reste modifiable. Introuvable, il est gardé tel quel (libellé type/id).

Le slot reclamant remplace l'étape par la recherche de l'outil. Seule la provenance du contact reste au-dessus quand l'étape est la première : elle est exigée pour avancer.

<creer-sollicitation-form reclamant-mode="step">
  <template #reclamant="{ reclamant, select }">
    <ma-recherche :valeur="reclamant" @choisi="select({ type: $event.type, id: $event.id, libelle: $event.nom })" />
  </template>
</creer-sollicitation-form>

| Clé du scope | Valeur | | ------------ | ------------------------------------------------------ | | reclamant | le réclamant sélectionné (ou null) | | select | select({ type, id, libelle }) : choisit le réclamant |

Champs figés (readonly)

Une seule prop, trois formes :

<!-- tout se saisit (défaut) -->
<creer-sollicitation-form :readonly="false" />

<!-- partiel : l'outil impose le réclamant et le canal -->
<creer-sollicitation-form :readonly="['reclamant', 'provenance']" />

<!-- tout est figé : l'utilisateur relit et valide -->
<creer-sollicitation-form readonly />

| Champ | Figé, il affiche… | … et l'assistant ne fait plus | | ------------- | -------------------------------------------------------------------- | ----------------------------------------------- | | reclamant | son libellé | — | | provenance | le canal (icône + libellé) | — | | motif | la chaîne catégorie › type › nature › motif ; motifs associés grisés | — | | cible | un résumé par ligne | déduire la cible du réclamant ou de ses modules | | description | le texte | — | | dateFaits | la date | — | | responsable | son nom, ou « Déterminé automatiquement » | suggérer un responsable d'après le paramétrage | | fichier | le document, sans ajout ni suppression | — |

La liste est exportée (READONLY_FIELDS) et une valeur inconnue est signalée par Vue.

Un champ figé affiche ce qu'on lui fournit, par reclamants et modelValue. Les champs obligatoires restent exigés pour avancer : figer provenance, motif, cible ou description engage l'outil à les fournir, sans quoi l'utilisateur reste bloqué à l'étape. Un responsable figé et vide est déterminé côté serveur.

Restreindre la nomenclature

nomenclatureFilter est un prédicat qui reçoit le motif entier : on filtre sur n'importe quel champ, pas seulement sur les identifiants.

// Sur une demande, seuls certains motifs sont proposables (règle d'office de Cally).
(motif, { reclamant }) => reclamant?.type !== 'D' || MOTIFS_DEMANDE.includes(motif.id)

// N'importe quel champ du référentiel fait l'affaire.
(motif) => !motif.libelle.startsWith('[INTERNE]')

Il s'applique à la recherche et à la sélection guidée, et il est rejoué quand le réclamant change. Absent, toute la nomenclature active est proposée.

Le brouillon (v-model)

{
  reclamant: { type, id },
  provenance: 'T',                          // code KRCLENT.CTRANS (cf. prop `provenances`)
  lignes: [ lignePrincipale, ...motifsAssociés ],
}

Un brouillon partiel suffit : il est fusionné avec le squelette (getDefaultDraft, getDefaultLigne, getDefaultPatrimoine, exportés), l'appelant n'a pas à connaître toutes les clés.

Une ligne :

| Clé | Rôle | | ---------------------------------------------- | ------------------------------------------------------------------- | | idCategorie, idType, idNature, idMotif | nomenclature (hiérarchique : changer un niveau efface les suivants) | | cibleMode | contrat, patrimoine ou demande (voir ci-dessous) | | patrimoine | localisation : commune, adresse, étage, module… | | contratReclamant, contratCible | contrat ciblé en mode contrat | | reprendreLocataireActuel | viser l'occupant actuel du module plutôt que le contrat ciblé | | modulePrecis | mode patrimoine : un module (true) ou les parties communes | | description, dateFaits | détail (dateFaits en timestamp Unix) | | responsable | collaborateur, ou son id ; null = déterminé côté serveur | | fichier | document joint (AmsomUploadFile), envoyé après la création |

  • Cible (cibleMode) :
    • contrat : un contrat et l'un de ses modules. C'est celui du réclamant si contratReclamant, sinon le contratCible trouvé par la recherche. Quand ce contrat n'occupe plus le module, reprendreLocataireActuel bascule sur son occupant actuel ;
    • patrimoine : modulePrecis choisit entre un module précis (obligatoire) et les parties communes (une adresse, un étage au plus, jamais de module) ;
    • demande : la demande elle-même, pour un réclamant demande.
  • Héritage des motifs associés : lignes[0] porte toujours sa cible et son détail. Sur une ligne associée :
    • description: null = hérite de la principale, une valeur la surcharge ;
    • la cible se surcharge par cibleOverride ;
    • la date se surcharge par dateFaitsOverride, parce que null est une date valide (« pas de date ») et ne peut pas marquer l'héritage ;
    • le responsable n'hérite jamais.

La création

beforeCreate expose le corps envoyé à POST /v2/cresol/creer_sollicitation. L'héritage y est déjà résolu : chaque ligne est autonome et porte les mêmes clés.

{
  typeReclamant: 'L',
  reclamant: 2200523,
  provenance: 'T',
  lignes: [
    {
      categorie, type, nature, motif,
      description, dateFaits, responsable,   // responsable : id ou null
      patrimoine,                             // absent quand la cible est la demande
      codeTypeCible, idCible,                 // cible contractuelle explicite…
      deduireCible                            // …ou à déduire du module par le serveur
    }
  ]
}

L'API renvoie les sollicitations créées (une par ligne). Chaque document joint part ensuite par POST /v2/cresol/upload_sollicitation_ged, apparié à la sollicitation du même motif. Le fichier ne figure jamais dans le corps de création.

Exports

import {
  CreerSollicitationForm,
  CreerSollicitationModal,
  configureCresol, // configuration du transport
  resetCresolCache, // vide le cache des référentiels
  getDefaultDraft, // squelettes du brouillon
  getDefaultLigne,
  getDefaultPatrimoine,
  READONLY_FIELDS, // champs acceptés par `readonly`
  PROVENANCES_CONTACT_DEFAUT, // codes proposés par défaut (prop `provenances`)
  PROVENANCE_CONTACT_ICONS, // { code: icône }
  DEFAULT_PROVENANCE_CONTACT
} from '@amsom-habitat/cresol'

Les référentiels et l'arbre patrimonial sont mis en cache au niveau du module, par API : deux ouvertures de l'assistant ne rechargent rien. resetCresolCache() le vide (changement d'utilisateur, tests).

Endpoints consommés

| Méthode | Chemin | Usage | | ------- | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------- | | GET | /v2/sollicitation/{motifs,categories,types,natures,etats} | Nomenclature (sans jeton) | | GET | /v2/sollicitation/responsables | Paramétrage des responsables | | GET | /collaborateurs?actif=true | Responsables proposables | | GET | /communes · /v2/patrimoine/{entrees,modules} | Arbre patrimonial (cible) | | GET | /v2/patrimoine/contrat_modules | Modules d'un contrat | | GET | /v2/patrimoine/contrat_module_rechercher?recherche= | Recherche libre de contrat | | GET | /v2/cresol/reclamant_rechercher?categorie=&recherche= | Recherche de réclamant (step) ; categorie = une catégorie, une liste a,b ou tout | | POST | /v2/cresol/creer_sollicitation | Création (1 à n lignes) | | POST | /v2/cresol/upload_sollicitation_ged | Document joint à une ligne |

Développement

npm i
cp .env.example .env   # VITE_API_URL=http://…
npm run storybook      # http://localhost:6006
npm run lint
npm run build

Les stories parlent à une vraie API : la nomenclature, le patrimoine et les collaborateurs viennent du serveur désigné par .env. Les contrôles baseUrl et token permettent de surcharger ponctuellement ; ils sont conservés d'une story à l'autre et au rechargement (localStorage), et le jeton est renouvelé sur place par un refresh 449. Le journal sous chaque story liste les événements émis, avec leur charge utile.

Les stories n'embarquent aucun identifiant de réclamant : une story soumise crée une vraie sollicitation, et un identifiant fictif y laisserait un réclamant inexistant. Les contrôles idContrat et idDemande désignent un dossier réel de l'API visée et sont conservés comme baseUrl / token. Tant que rien n'est saisi, ils valent les dossiers de recette idContrat: 2251519 et idDemande: 2256564 (EXEMPLES dans .storybook/preview.js). Vidés, le réclamant n'est pas proposé, et une story qui en attend un affiche un avertissement au lieu du formulaire.

| Story | Montre | | ----------------------------------------------------------------- | ----------------------------------------------------------------------------- | | Contrat | cas courant, volet à onglets + nbSimilaires | | Demande | réclamant demande + nomenclatureFilter | | PlusieursReclamants | plusieurs réclamants, reclamantMode select/switch/autoc. | | ReclamantRecherche / ReclamantRechercheRestreinte | mode step, toutes catégories / typesReclamant | | ReclamantRechercheSurchargee | slot reclamant | | BrouillonPrealimente | modelValue partiel | | ReclamantEtProvenanceFiges / Relecture | readonly partiel / total | | ProvenancesRestreintes / ProvenancesToutesSaufExclues | provenances / provenances: null + provenancesExclues | | SansVolet / VoletRemplace | aside: false / slot aside | | InterceptionAvantCreation | beforeCreate : payload enrichi + waitUntil | | Defaut (modale) | ouverture, close, closeOnCreated | | DuplicationApresCreation (…Etape) / EnchainementAutomatique | (modale) enchaîner les créations avec un brouillon dupliqué (étape réclamant) |

Organisation du code

src/
  CreerSollicitationForm.vue    racine : fournit brouillon, données et options ; porte la création
  CreerSollicitationModal.vue   coquille modale (props et événements relayés)
  props.js                      contrat public unique (props + événements)
  components/                   étapes et blocs de saisie (lisent le brouillon injecté)
  composables/
    useSollicitationDraft.js    le brouillon : état, validation, champs figés, payload
    useCresolData.js            référentiels et patrimoine (cache module, par API)
    useCresolContext.js         options de l'outil (injectées, sans prop-drilling)
  api/                          un fichier par domaine ; transport/ = axios-overlay + jeton
  utils/                        fonctions pures (texte, dates, erreurs, icônes)

Toute la logique de saisie (héritage, validation, champs figés, payload) vit dans useSollicitationDraft : les composants ne font qu'afficher et appeler ses setters.

Publier

Le numéro de package.json doit avoir son entrée ## VX.Y.… dans changelog.md (check-version.sh).

make publish         # main : lint, build, tag, npm publish
make alpha_publish   # dev : version prerelease beta