@mostajs/flotte-ui 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -1
- package/README.md +34 -8
- package/llms.txt +34 -7
- package/package.json +5 -5
- package/src/commun.js +84 -0
- package/src/formulaires.js +330 -0
- package/src/index.js +8 -2
- package/src/kit.js +36 -0
- package/src/rendu.js +346 -138
- package/src/textes.js +68 -9
- package/src/vue.js +125 -11
package/CHANGELOG.md
CHANGED
|
@@ -3,7 +3,54 @@
|
|
|
3
3
|
Format [Keep a Changelog](https://keepachangelog.com/fr/1.0.0/) · [SemVer](https://semver.org/lang/fr/).
|
|
4
4
|
Auteur : Dr Hamid MADANI <drmdh@msn.com>
|
|
5
5
|
|
|
6
|
-
## [0.
|
|
6
|
+
## [0.2.1] — non publiée
|
|
7
|
+
### Added
|
|
8
|
+
- Option `pieces: false` du rendu et des lecteurs. Elle s'adresse à une application qui ne reçoit pas de fichiers :
|
|
9
|
+
- plus de champ fichier, et des formulaires urlencoded, non multipart ;
|
|
10
|
+
- les lecteurs ignorent une pièce qui n'a pas été offerte.
|
|
11
|
+
|
|
12
|
+
Elle répond à la console de Guerway, qui n'accepte que l'urlencoded. Essai T-FUI-27.
|
|
13
|
+
- Option de rendu `codeSite(code)` : le code de station affiché, choisi par l'application. Guerway saisit `alg-01`
|
|
14
|
+
et affiche `ALG-01`. Essai T-FUI-28.
|
|
15
|
+
|
|
16
|
+
## [0.2.0] — 2026-10-24
|
|
17
|
+
Les planches A à F de Guerway (`GUERWAY/docs/L0/maquette-flotte/`, exigences ECR-16.29 à 16.41). Demande
|
|
18
|
+
`@mostajs/flotte` **^0.5.0** (`TRANSITIONS`, `transitionsDepuis`, pièce d'un plein).
|
|
19
|
+
### Added
|
|
20
|
+
- Tableau de bord de la planche A : six indicateurs (« Hors service »), puces de statut avec effectifs, liste
|
|
21
|
+
(type et capacité, station et région), véhicules par station en barres empilées, statuts en anneau. Essais
|
|
22
|
+
T-FUI-12 et 13.
|
|
23
|
+
- `rendrePageVehicule` : la fiche pleine page. Elle comprend :
|
|
24
|
+
- un en-tête commun, « Modifier », et « Changer le statut » limité aux transitions du moteur ;
|
|
25
|
+
- sept onglets ;
|
|
26
|
+
- un bandeau de message ou de refus.
|
|
27
|
+
|
|
28
|
+
Essai T-FUI-14.
|
|
29
|
+
- Les onglets :
|
|
30
|
+
- Documents : une carte par échéance. Essai T-FUI-15.
|
|
31
|
+
- Entretiens : jauges km et jours, prochaine échéance estimée, interventions à cadenas. Essai T-FUI-16.
|
|
32
|
+
- Affectations : frise et panneau « Affecter un chauffeur ». Essai T-FUI-17.
|
|
33
|
+
- Pleins et relevés : courbe du compteur, avertissements, consommation mesurée. Essai T-FUI-19.
|
|
34
|
+
- Coûts : périodes, postes, non comptés, barres par mois, coût au km du parc. Essai T-FUI-20.
|
|
35
|
+
- Les formulaires d'écriture et leurs **lecteurs**. Le module n'écrit rien : un lecteur rend les arguments de l'API
|
|
36
|
+
de `flotte`.
|
|
37
|
+
- `rendreFormulaireStatut` et `lireStatut` (T-FUI-18).
|
|
38
|
+
- `rendreFormulaireVehicule`, `lireFormulaireVehicule` et `lireModification` (T-FUI-21, 22).
|
|
39
|
+
- `FORMULAIRES`, `rendreFormulaire` et `lireFormulaire` : plan, intervention, clôture, plein, relevé, échéance
|
|
40
|
+
(T-FUI-23).
|
|
41
|
+
- `erreurDeFlotte` place un refus du moteur sous son champ.
|
|
42
|
+
- `construireMonVehicule` et `rendreMonVehicule` : « Mon véhicule » du livreur. Essai T-FUI-24.
|
|
43
|
+
- `construireAptitudes`, `rendreChoixVehicule`, `rendreRefusDepart` et `rendreDisponibles` : l'aptitude en tournée,
|
|
44
|
+
avec le refus et **tous** ses motifs. Essai T-FUI-25.
|
|
45
|
+
- Essai transverse T-FUI-26 : aucun script, tout est échappé, et chaque clé de texte appelée existe.
|
|
46
|
+
### Changed
|
|
47
|
+
- Vue-modèle de la fiche :
|
|
48
|
+
- `documents`, `entretiens` et `affectations` changent de forme (plan de dev §8.3) ;
|
|
49
|
+
- `ONGLETS` compte sept onglets ;
|
|
50
|
+
- `indicateurs.horsService` et `puces` apparaissent.
|
|
51
|
+
- La colonne « Capacité » passe sous le type.
|
|
52
|
+
|
|
53
|
+
## [0.1.1] — 2026-10-24
|
|
7
54
|
### Fixed
|
|
8
55
|
- Une entrée d'historique sans `vers` (modification descriptive, `@mostajs/flotte` ≥ 0.4.0) n'est plus lue comme un
|
|
9
56
|
changement de statut : la variation des indicateurs reste juste. L'onglet Historique l'affiche
|
package/README.md
CHANGED
|
@@ -6,16 +6,28 @@ Les écrans du carnet du parc ([`@mostajs/flotte`](../mosta-flotte)), en HTML re
|
|
|
6
6
|
script**. Le module sert le même écran à Guerway et au SaaS « Carnet du parc ». Chacun l'habille de sa propre charte.
|
|
7
7
|
|
|
8
8
|
- **Le tableau de bord** (écran ECR-16 de Guerway) :
|
|
9
|
-
-
|
|
9
|
+
- six indicateurs avec leur variation sur la période, et des puces de statut avec leurs effectifs ;
|
|
10
10
|
- la liste filtrée et paginée, avec le statut, l'indicateur « document expiré » et la réponse « peut partir » du
|
|
11
11
|
jour ;
|
|
12
12
|
- les alertes et échéances ;
|
|
13
13
|
- la répartition par type, les statuts et le kilométrage sur six mois ;
|
|
14
|
-
- les véhicules par station, le top 5 et les actions rapides.
|
|
15
|
-
- **La fiche du véhicule
|
|
14
|
+
- les véhicules par station (barres empilées par statut), le top 5 et les actions rapides.
|
|
15
|
+
- **La fiche du véhicule**, en panneau ou en pleine page (`rendrePageVehicule`) :
|
|
16
16
|
- le bandeau « peut partir », ou ses motifs ;
|
|
17
|
-
-
|
|
18
|
-
-
|
|
17
|
+
- « Modifier », et « Changer le statut », qui ne propose que les transitions permises par le moteur ;
|
|
18
|
+
- sept onglets, chacun en lien GET :
|
|
19
|
+
- Informations ;
|
|
20
|
+
- Documents : une carte par échéance, avec la pièce et son empreinte ;
|
|
21
|
+
- Entretiens : jauges en km et en jours, prochaine échéance datée, même quand la date est estimée ;
|
|
22
|
+
- Affectations : frise, et choix d'un chauffeur du bureau ;
|
|
23
|
+
- Pleins et relevés : courbe du compteur et consommation mesurée ;
|
|
24
|
+
- Coûts : par période et par mois, coût au km du parc ;
|
|
25
|
+
- Historique.
|
|
26
|
+
- **Les formulaires d'écriture**, avec leurs lecteurs :
|
|
27
|
+
- nouveau véhicule, modifier, changement de statut, réforme confirmée ;
|
|
28
|
+
- plan, intervention, clôture, plein, relevé, échéance.
|
|
29
|
+
- **« Mon véhicule »** du livreur, et l'**aptitude des véhicules** au départ d'une tournée, avec un refus qui donne
|
|
30
|
+
tous ses motifs.
|
|
19
31
|
|
|
20
32
|
L'écran se fait en deux temps :
|
|
21
33
|
1. **construire** : lit l'API de `flotte` et produit une vue-modèle faite de codes ;
|
|
@@ -60,6 +72,19 @@ Le kit reprend les signatures des composants de Guerway (`src/charte.mjs`), qui
|
|
|
60
72
|
|
|
61
73
|
Un membre absent est pris dans `KIT_DEFAUT`.
|
|
62
74
|
|
|
75
|
+
### Écrire : le module lit, l'application appelle le moteur
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
import { lireFormulaire, rendreFormulaire, erreurDeFlotte } from '@mostajs/flotte-ui';
|
|
79
|
+
|
|
80
|
+
const { donnees, erreurs } = lireFormulaire('plein', req.body); // « 18 500,00 » → 18500, JJ/MM/AAAA → AAAA-MM-JJ
|
|
81
|
+
if (!Object.keys(erreurs).length) {
|
|
82
|
+
try { await flotte.saisirPlein({ vehicule: id, ...donnees }, { agent }); return redirect(`/flotte/${id}?onglet=pleins`); }
|
|
83
|
+
catch (refus) { /* RECUL : sous le champ km, formulaire rempli */ return page(rendreFormulaire('plein', { fiche, valeurs: req.body, refus }, opts)); }
|
|
84
|
+
}
|
|
85
|
+
return page(rendreFormulaire('plein', { fiche, valeurs: req.body, erreurs }, opts));
|
|
86
|
+
```
|
|
87
|
+
|
|
63
88
|
## Langues
|
|
64
89
|
|
|
65
90
|
Le module ne contient aucune chaîne en dur.
|
|
@@ -72,12 +97,13 @@ Le module ne contient aucune chaîne en dur.
|
|
|
72
97
|
- Écrire ou décider : c'est `@mostajs/flotte`, qui porte toutes les règles.
|
|
73
98
|
- Router, poser le menu ou vérifier les droits : c'est l'application. `droits.gerer` ne fait que masquer, le serveur
|
|
74
99
|
refuse.
|
|
75
|
-
-
|
|
76
|
-
|
|
100
|
+
- Stocker un fichier joint (pièce d'une échéance, ticket d'un plein) : l'application le reçoit, le garde, et passe
|
|
101
|
+
à `flotte` son nom et son empreinte.
|
|
102
|
+
- Connaître le permis d'un chauffeur : l'application fournit `chauffeurs` (`permis`, `habilite`).
|
|
77
103
|
|
|
78
104
|
## Vérifier
|
|
79
105
|
|
|
80
106
|
```bash
|
|
81
|
-
npm test # T-FUI-1 à
|
|
107
|
+
npm test # T-FUI-1 à 26
|
|
82
108
|
node examples/verifier.mjs # écrit test-scripts/.out/exemple-flotte-ui.html (le parc de la maquette)
|
|
83
109
|
```
|
package/llms.txt
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# @mostajs/flotte-ui — llms.txt
|
|
2
2
|
|
|
3
3
|
RÔLE
|
|
4
|
-
Écrans HTML du carnet du parc (@mostajs/flotte), sans React ni script : tableau de bord ECR-16 de Guerway
|
|
5
|
-
du véhicule
|
|
4
|
+
Écrans HTML du carnet du parc (@mostajs/flotte), sans React ni script : tableau de bord ECR-16 de Guerway, fiche
|
|
5
|
+
du véhicule pleine page à sept onglets, formulaires d'écriture et leurs lecteurs, « Mon véhicule » du livreur,
|
|
6
|
+
aptitude en tournée (planches A à F, 0.2.0). Deux temps : construire (async, lit l'API de flotte → vue-modèle de CODES) puis rendre (pur,
|
|
6
7
|
vue-modèle → HTML, avec le kit et la traduction de l'application). N3, métier, forme « vue ».
|
|
7
8
|
|
|
8
9
|
EXPORTS
|
|
@@ -14,11 +15,33 @@ EXPORTS
|
|
|
14
15
|
{ sens, pct|null, favorable }), liste: { lignes, total, page, pages, parPage }, options, alertes: { lignes, total, jours },
|
|
15
16
|
repartition, statuts, km: { mois, valeurs }, parSite, top, avecActivite, fiche }
|
|
16
17
|
ligne = { id, code, plaque, type, capacite: { kg, m3 }, site, region, conducteur, km, statut, documentExpire, depart }
|
|
17
|
-
construireFiche(flotte, id, { declarations, date?, sites?, conducteurs?, onglet? }) -> fiche
|
|
18
|
-
onglet ∈ ONGLETS (informations, documents, entretiens, affectations, historique) ; inconnu → informations
|
|
18
|
+
construireFiche(flotte, id, { declarations, date?, sites?, conducteurs?, agents?, onglet?, chauffeurs?, periode?, perimetre? }) -> fiche
|
|
19
|
+
onglet ∈ ONGLETS (informations, documents, entretiens, affectations, pleins, couts, historique) ; inconnu → informations
|
|
20
|
+
fiche.transitions (flotte.transitionsDepuis), categoriePermis, plans ; selon l'onglet : documents [{ type, etat, courante, anciennes }],
|
|
21
|
+
entretiens { plans [{ km|jours: { fait, pas, pct }, le, estime, auPlusTard }], interventions, rythme },
|
|
22
|
+
affectations { courante, frise, candidats [{ …chauffeur, disponibilite: libre|ce_vehicule|occupe, plaque? }], categorie },
|
|
23
|
+
pleins { km, rythme, courbe, releves, pleins [{ …, conso }], consommation }, couts { periode, du, au, cout, mois, parc, nonComptes }
|
|
24
|
+
chauffeurs : [{ id, nom, telephone, permis, habilite? }] fournis par l'application (permis et habilitation : les siens)
|
|
25
|
+
periode : 'mois'|'trimestre'|'annee'|{ du, au } (la requête GET convient) ; periodeDe(p, jour)
|
|
26
|
+
construireMonVehicule(flotte, conducteur, opts) -> { vehicule: fiche|null, prochains, rythme }
|
|
27
|
+
construireAptitudes(flotte, { date?, conducteur?, perimetre?, sites? }) -> [{ id, plaque, type, capacite, km, site, region, depart }] aptes d'abord
|
|
19
28
|
rendreTableau(vm, { kit?, t?, locale?, liens?: { base, nouveau?, modifier?(id), affecter?(id), planifier?(id), tournee?,
|
|
20
29
|
alertes?, export? }, droits?: { gerer }, declarations? }) -> { titre, sousTitre, outils, corps }
|
|
21
|
-
rendreFiche(fiche, mêmes opts + filtres?) -> HTML
|
|
30
|
+
rendreFiche(fiche, mêmes opts + filtres?) -> HTML (panneau du tableau de bord)
|
|
31
|
+
rendrePageVehicule(fiche, opts + { message?, refus?, devise? }) -> { titre, sousTitre, fil, outils, corps }
|
|
32
|
+
liens : fiche(id, onglet), modifier, statut(id, t), renouveler(id, type), piece(id, e), planifier, intervention, clore(id, i),
|
|
33
|
+
affecter, liberer, plein, releve — chaque écriture est un formulaire POST vers le lien fourni
|
|
34
|
+
rendreFormulaireVehicule({ mode, vehicule?, declarations, sites, valeurs?, erreurs?, refus? }, opts + liens.enregistrer)
|
|
35
|
+
lireFormulaireVehicule(corps, { declarations }) -> { donnees: { code, immatriculation, type, attributs, chassis, miseEnService,
|
|
36
|
+
site, mode, kmDepart, echeances }, erreurs } inscrire(donnees), puis relever(kmDepart), poserEcheance(…)
|
|
37
|
+
lireModification(corps, vehicule, { declarations }) -> { donnees (champs changés seuls, pour modifier), erreurs }
|
|
38
|
+
rendreFormulaireStatut(fiche, transition, opts) ; lireStatut(corps, transition) -> { donnees: { motif, confirme }, erreurs }
|
|
39
|
+
FORMULAIRES { plan, intervention, cloture, plein, releve, echeance } ; rendreFormulaire(nom, { fiche, declarations?, valeurs?,
|
|
40
|
+
erreurs?, refus? }, opts + action) ; lireFormulaire(nom, corps, { declarations? }) -> { donnees, erreurs }
|
|
41
|
+
codeSite?: (code) → code affiché (rendu, 0.2.1) ; pieces: false (rendu et lecteurs, 0.2.1) : ni champ fichier ni multipart, pour une application sans dépôt de fichiers
|
|
42
|
+
erreurDeFlotte(e) -> { champ, code } le refus du moteur sous son champ (RECUL → km, DOUBLON → immatriculation…)
|
|
43
|
+
rendreMonVehicule(vm, { liens: { plein, releve } }) ; rendreChoixVehicule(aptitudes, { nom?, choisi? })
|
|
44
|
+
rendreRefusDepart(depart, { lien }) ; rendreDisponibles(aptitudes, { exclure })
|
|
22
45
|
exporterCsv(vm, opts?) -> CSV « ; » (construire avec parPage: Infinity)
|
|
23
46
|
TEXTES, texte(cle, t?, vars?) t('flotte.ecran.<cle>') puis repli français
|
|
24
47
|
KIT_DEFAUT { icone, kpi, badge, carte, alerte, anneau, courbes, pagination, classes } ; FLOTTE_CSS (classes fl-*) ; COULEURS
|
|
@@ -29,14 +52,18 @@ RÈGLES
|
|
|
29
52
|
- Le texte cherche aussi le NOM du chauffeur (le moteur ne connaît que l'identifiant).
|
|
30
53
|
- « Document expiré » est un indicateur (pastille), jamais un statut.
|
|
31
54
|
- Une action n'apparaît que si son lien est fourni ; une action d'écriture, que si droits.gerer.
|
|
55
|
+
- Le module n'écrit rien : un lecteur signale les champs mal formés (requis, nombre, date) et rend les arguments du
|
|
56
|
+
moteur ; les règles (motif de plaque, doublon, recul, transition) restent au moteur, dont le refus revient sous
|
|
57
|
+
son champ, formulaire rempli.
|
|
58
|
+
- Le menu « Changer le statut » ne montre que transitionsDepuis(statut) ; la catégorie de permis vient du type (D23).
|
|
32
59
|
|
|
33
60
|
PIÈGES
|
|
34
61
|
- Toute valeur est échappée ; titre et corps des cartes du kit reçoivent du HTML déjà sûr.
|
|
35
62
|
- Les nombres sont formatés par Intl (fr-FR : espace fine insécable U+202F) : en test, accepter [\s ].
|
|
36
|
-
- Dépend de @mostajs/flotte ^0.
|
|
63
|
+
- Dépend de @mostajs/flotte ^0.5.0 (vehicules, vehiculeDe, pleins, transitionsDepuis) en peerDependency : l'application fournit l'instance.
|
|
37
64
|
|
|
38
65
|
EXEMPLE / TEST
|
|
39
66
|
examples/verifier.mjs le parc de la maquette, page complète → test-scripts/.out/exemple-flotte-ui.html
|
|
40
|
-
test-scripts/unit/flotte-ui.test.mjs T-FUI-1 à
|
|
67
|
+
test-scripts/unit/flotte-ui.test.mjs T-FUI-1 à 11 ; flotte-ui-planches.test.mjs T-FUI-12 à 26 (planches A à F)
|
|
41
68
|
|
|
42
69
|
LICENCE AGPL-3.0-or-later · Auteur Dr Hamid MADANI <drmdh@msn.com>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mostajs/flotte-ui",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Écrans HTML du carnet du parc (@mostajs/flotte), sans React ni script : tableau de bord (
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Écrans HTML du carnet du parc (@mostajs/flotte), sans React ni script : tableau de bord, fiche du véhicule pleine page à sept onglets (documents, entretiens, affectations, pleins et relevés, coûts, historique), formulaires d'écriture et leurs lecteurs, « Mon véhicule » du livreur, aptitude en tournée. Vue-modèle lue dans l'API de flotte, rendue avec le kit de composants de l'application (sa charte) ou un kit sobre par défaut.",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"author": "Dr Hamid MADANI <drmdh@msn.com>",
|
|
7
7
|
"type": "module",
|
|
@@ -13,15 +13,15 @@
|
|
|
13
13
|
"keywords": ["mostajs", "flotte", "fleet", "fleet-management", "html", "server-side", "no-react", "dashboard"],
|
|
14
14
|
"repository": { "type": "git", "url": "https://github.com/apolocine/mosta-flotte-ui" },
|
|
15
15
|
"dependencies": { "@mostajs/app-shell-ui": "^0.3.0" },
|
|
16
|
-
"peerDependencies": { "@mostajs/flotte": "^0.
|
|
16
|
+
"peerDependencies": { "@mostajs/flotte": "^0.5.0" },
|
|
17
17
|
"devDependencies": { "@mostajs/mjs-unit": "0.10.0" },
|
|
18
18
|
"mostajs": {
|
|
19
19
|
"niveau": "N3", "nature": "metier", "reutilisabilite": "mono-domaine", "depend_de": ["@mostajs/flotte", "@mostajs/app-shell-ui"],
|
|
20
20
|
"question": "Comment le chef de parc voit-il son parc, et chaque véhicule, sans React ?",
|
|
21
21
|
"forme": "vue",
|
|
22
22
|
"entites": [],
|
|
23
|
-
"verbes": ["construireTableau", "rendreTableau", "construireFiche", "rendreFiche", "exporterCsv"],
|
|
23
|
+
"verbes": ["construireTableau", "rendreTableau", "construireFiche", "rendreFiche", "rendrePageVehicule", "exporterCsv", "rendreFormulaireVehicule", "lireFormulaireVehicule", "lireModification", "rendreFormulaireStatut", "lireStatut", "rendreFormulaire", "lireFormulaire", "erreurDeFlotte", "construireMonVehicule", "rendreMonVehicule", "construireAptitudes", "rendreChoixVehicule", "rendreRefusDepart", "rendreDisponibles"],
|
|
24
24
|
"interop": { "moteur": "@mostajs/flotte (vehicules, peutPartir, prochainsEntretiens, echeances, releves, affectations)", "primitives": "@mostajs/app-shell-ui (esc, pagination)", "charte": "kit de composants injecté par l'application" },
|
|
25
|
-
"ne_fait_pas": { "stocker, calculer une règle de flotte": "@mostajs/flotte", "gabarit, menu, routes": "l'application (ou @mostajs/app-shell-ui)", "droits": "l'application (droits.gerer)" }
|
|
25
|
+
"ne_fait_pas": { "stocker, écrire, calculer une règle de flotte": "@mostajs/flotte (les lecteurs rendent ses arguments)", "gabarit, menu, routes": "l'application (ou @mostajs/app-shell-ui)", "droits": "l'application (droits.gerer)" }
|
|
26
26
|
}
|
|
27
27
|
}
|
package/src/commun.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// @mostajs/flotte-ui — ce que partagent le rendu des écrans et celui des formulaires : contexte, liens, formats.
|
|
2
|
+
// Author: Dr Hamid MADANI <drmdh@msn.com> · AGPL-3.0-or-later
|
|
3
|
+
import { esc } from '@mostajs/app-shell-ui';
|
|
4
|
+
import { libelle } from '@mostajs/flotte';
|
|
5
|
+
import { texte } from './textes.js';
|
|
6
|
+
import { KIT_DEFAUT } from './kit.js';
|
|
7
|
+
|
|
8
|
+
export const BADGE = { en_service: ['vert', 'coche'], a_l_atelier: ['orange', 'cle'], immobilise: ['rouge', 'croix'], reforme: ['gris', 'document'] };
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Le contexte de rendu : kit complété, traduction, formats. opts : { kit, t, locale, liens, droits, declarations, devise,
|
|
12
|
+
* codeSite? (code → code affiché : Guerway saisit alg-01 et affiche ALG-01) }
|
|
13
|
+
*/
|
|
14
|
+
export function contexte({ kit = {}, t, locale = 'fr-FR', liens = {}, droits = {}, declarations = {}, devise = '', codeSite } = {}) {
|
|
15
|
+
const k = { ...KIT_DEFAUT, ...kit, classes: { ...KIT_DEFAUT.classes, ...(kit.classes || {}) } };
|
|
16
|
+
const nf = (x) => new Intl.NumberFormat(locale).format(x);
|
|
17
|
+
const nf2 = (x) => new Intl.NumberFormat(locale, { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(x);
|
|
18
|
+
const argent = (x) => (x === null || x === undefined ? '—' : `${nf2(x)}${devise ? ` ${devise}` : ''}`);
|
|
19
|
+
const tx = (cle, vars) => texte(cle, t, vars);
|
|
20
|
+
// Un code de la flotte ; à défaut de traduction, le libellé déclaré, sinon le code.
|
|
21
|
+
const lib = (famille, code, vars) => {
|
|
22
|
+
const l = libelle(famille, code, t, vars);
|
|
23
|
+
if (l !== code) return l;
|
|
24
|
+
const d = famille === 'type' ? declarations.types?.[code] : famille === 'echeance' ? declarations.echeances?.[code] : null;
|
|
25
|
+
return d?.libelle ?? code;
|
|
26
|
+
};
|
|
27
|
+
const jj = (d) => (d ? d.split('-').reverse().join('/') : '—');
|
|
28
|
+
/** Une phrase de motif ou d'avertissement : les valeurs qui sont des codes sont traduites, les dates mises en forme. */
|
|
29
|
+
const phrase = (famille, m) => {
|
|
30
|
+
const v = { ...m };
|
|
31
|
+
if (v.statut) v.statut = lib('statut', v.statut);
|
|
32
|
+
if (v.type) v.type = lib('echeance', v.type);
|
|
33
|
+
if (v.unite) v.unite = lib('unite', v.unite);
|
|
34
|
+
if (v.date) v.date = jj(v.date);
|
|
35
|
+
if (Number.isFinite(v.n)) v.n = nf(v.n);
|
|
36
|
+
return lib(famille, m.code, v);
|
|
37
|
+
};
|
|
38
|
+
const site = (c) => (c === null || c === undefined || c === '' ? '—' : typeof codeSite === 'function' ? String(codeSite(c)) : String(c));
|
|
39
|
+
return { k, c: k.classes, nf, nf2, argent, devise, tx, lib, jj, phrase, site, liens, droits, peutGerer: Boolean(droits.gerer), locale };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const nonVide = ([, v]) => v !== undefined && v !== null && v !== '';
|
|
43
|
+
const requete = (params) => Object.entries(params).filter(nonVide).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join('&');
|
|
44
|
+
/** Une URL GET : la base, puis les paramètres non vides, dans l'ordre donné. */
|
|
45
|
+
export function url(base, params) { const q = requete(params); return q ? `${base}?${q}` : base; }
|
|
46
|
+
/** Ajoute des paramètres à une URL qui en a peut-être déjà (celle que rend un lien de l'application). */
|
|
47
|
+
export function avec(href, params) { const q = requete(params); return q ? `${href}${href.includes('?') ? '&' : '?'}${q}` : href; }
|
|
48
|
+
/** Les champs cachés qui reportent la requête d'une action GET (un formulaire GET remplace la requête de son action). */
|
|
49
|
+
export function caches(href) {
|
|
50
|
+
const [chemin, q = ''] = href.split('?');
|
|
51
|
+
const champs = q ? q.split('&').map((p) => p.split('=').map(decodeURIComponent)) : [];
|
|
52
|
+
return { chemin, html: champs.map(([k, v]) => `<input type="hidden" name="${esc(k)}" value="${esc(v ?? '')}">`).join('') };
|
|
53
|
+
}
|
|
54
|
+
export const garder = (f = {}) => ({ q: f.q, type: f.type, statut: f.statut, region: f.region, ...(f.page > 1 ? { page: f.page } : {}) });
|
|
55
|
+
|
|
56
|
+
/** Le lien d'un onglet de la fiche : la fiche pleine page si l'application la fournit, sinon le tableau de bord. */
|
|
57
|
+
export function lienFiche(x, id, onglet = 'informations', extra = {}, filtres = {}) {
|
|
58
|
+
const o = onglet === 'informations' ? '' : onglet;
|
|
59
|
+
if (x.liens.fiche) return avec(x.liens.fiche(id, o), extra);
|
|
60
|
+
return url(x.liens.base || '', { ...garder(filtres), v: id, onglet: o, ...extra });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function delai(x, n) {
|
|
64
|
+
if (n === null || n === undefined) return '';
|
|
65
|
+
if (n < 0) return `<span class="fl-retard">(${esc(x.tx('info.depuisJours', { n: x.nf(-n) }))})</span>`;
|
|
66
|
+
if (n === 0) return `<span class="fl-delai">(${esc(x.tx('info.aujourdhui'))})</span>`;
|
|
67
|
+
return `<span class="fl-delai">(${esc(x.tx('info.dansJours', { n: x.nf(n) }))})</span>`;
|
|
68
|
+
}
|
|
69
|
+
export const badgeStatut = (x, s) => x.k.badge(x.lib('statut', s), ...(BADGE[s] || ['gris']));
|
|
70
|
+
export const capacite = (x, c) => [c.kg !== null && c.kg !== undefined ? `${x.nf(c.kg)} kg` : null, c.m3 !== null && c.m3 !== undefined ? `${x.nf(c.m3)} m³` : null].filter(Boolean).join(' / ') || '—';
|
|
71
|
+
|
|
72
|
+
/** Un tableau sobre ; `lignes` : cellules déjà en HTML. */
|
|
73
|
+
export function tableau(x, entetes, lignes, vide, { classeLigne } = {}) {
|
|
74
|
+
if (!lignes.length) return `<p class="fl-vide">${esc(vide)}</p>`;
|
|
75
|
+
return `<div class="fl-defile"><table class="${esc(x.c.tableau)}"><thead><tr>${entetes.map((e) => `<th scope="col">${esc(e)}</th>`).join('')}</tr></thead>`
|
|
76
|
+
+ `<tbody>${lignes.map((l, i) => `<tr${classeLigne?.(i) ? ` class="${classeLigne(i)}"` : ''}>${l.map((c) => `<td>${c}</td>`).join('')}</tr>`).join('')}</tbody></table></div>`;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Les bandeaux : succès (role=status) et refus (role=alert). Sans « × » : ils disparaissent au rechargement. */
|
|
80
|
+
export const bandeauOk = (x, texteHtml) => `<div class="fl-bandeau ok" role="status">${x.k.icone('coche', 18)}<div>${texteHtml}</div></div>`;
|
|
81
|
+
export const bandeauKo = (x, texteHtml) => `<div class="fl-bandeau ko" role="alert">${x.k.icone('croix', 18)}<div>${texteHtml}</div></div>`;
|
|
82
|
+
/** Le texte d'un refus du moteur (ErreurFlotte) ou d'une erreur quelconque : jamais le message technique. */
|
|
83
|
+
export const texteRefus = (x, e) => (e && typeof e.code === 'string' ? x.lib('erreur', e.code) : x.tx('message.erreur'));
|
|
84
|
+
export const bouton = (x, classe = '') => `${esc(x.c.btn)}${classe ? ` ${classe}` : ''}`;
|