[Laravel – Angular – Tailwind] Plateforme de rédaction de DUERP

Notre dernière plateforme développée from scratch et est un outil d’administration dans le domaine de la Gestion des Risques. Elle a été réalisée pour une coopérative qui regroupe plus 3000 entreprises pour les aider à rédiger des documents uniques d’évaluation des risques professionnels (DUERP). Ces documents longs et fastidieux à rédiger constitue une obligation légale pour les entreprises de plus de 1 salarié mais qui s’avère peu respectée.

Pour faciliter la rédaction de ces documents techniques, nous avons développé un outil permettant en quelques minutes d’établir un document au format PDF. Sans outil, il faudrait plusieurs heures pour rédiger le même document soi-même. L’application a été réalisée en lien avec une agence de communication pour le design.

Cet outil est une original pour nous d’un point de vue technique puisque nous avons combiné les frameworks Laravel, Angular, l’excellent Tailwind et Html2Pdf

Tailwind pour le meilleur et pour le meilleur

Alors que nous utilisions depuis plusieurs années le principale Framework CSS du marché : Bootstrap, nous avons décidé de nous essayer au fameux Tailwind.

Pour ce projet composé principalement de formulaires, une maquette complète nous a été fournie. Elle reprend les designs épurés et fonctionnels de Tailwind dans un thème aux couleurs de notre client.

L’intégration de Tailwind dans Angular est d’une facilité déconcertante ; exécuter ces deux lignes codes suffit :

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init

Suite la prise en main de Tailwind est bien plus facile que Bootstrap à mes yeux. Par exemple, les noms des classes sont intuitifs et la modulation intégrée allie parfaitement compréhension et concision.

Par exemple, besoin une bordure à votre div ? class = “border“

Besoin d’une bordure plus large ? class = “border-2“

Besoin d’une bordure rouge ? class = “border-2 border-red-600“

Finalement il faudrait une bordure plus claire ? class = “border-2 border-red-400“.

Et à votre avis comment passe-t-on la couleur du texte en vert foncé ? class = “text-green-800“

En quelque minutes à parcourir la documentation, on enregistre les principaux mots clés pour créer notre design.

Et si, comme nous, vous ne voulez pas des couleurs par défaut de Tailwind, vous pouvez très simplement les configurer. Ainsi dans le fichier de config de Tailwind, on ajoutera :

theme: {
    extend: {
      colors: {
        'vertSpecif': {
          100: '#ccfbf1',
          200: '#99f6e4',
          300: '#5eead4',
          400: '#2dd4bf',
          500: '#14b8a6',
          600: '#0d9488',
          700: '#0f766e',
          800: '#115e59',
          900: '#134e4a',
        },
      },

Ici on ajoute une couleur appelée « vertSpecif» avec différentes nuances de vert choisie par la graphiste de notre collaborateur.

Une fois que c’est fait, vous pouvez utiliser toutes les classes de Tailwind avec -vertSpecif (le nom de notre couleur). Donc si vous voulez une div de cette couleur « vert » claire avec du texte de couleur « vert » foncé (comme pour le niveau de gravité 3 de l’image ci-dessous), il suffit d’appliquer les classes suivantes :

class = “background-vertSpecif-300 text-vertSpecif-800“

Ce, n’importe où dans votre application !

Voici un des rendus de l’application réalisé intégralement avec Tailwind :

Angular et les formulaires dynamiques complexes

La difficulté principale du projet était la réalisation d’un formulaire dynamique. L’utilisateur peut ainsi ajouter autant de champ qu’il le souhaite et, en fonction des choix effectués, pouvoir également ajouter autant de sous champs qu’il le souhaite.

L’objectif final est de construire des données architecturées comme dans l’exemple suivant avec un unique formulaire :

"categories": [
        {
            "nom": "Catégorie 1",
            "situations": [
                {
                    "nom": "Toutes unités de travail",
                    "risques": [
                        {
                            "nom": "Arrivée de salariés",
                            "mesures": [
                                "Formation du salarié aux risques avant sa prise de poste",
                                "Présentation du Document Unique d'Evaluation des Risques",
                        },
                },
         },

Ici l’utilisateur doit pouvoir sélectionner autant de catégorie qu’il le souhaite et dans la catégorie « Catégorie 1 », pouvoir choisir autant de situation qu’il le souhaite, ici la situation « Toutes unités de travail » et ainsi de suite sur quatre échelons bien définit.

Pour réaliser ce formulaire, Angular nous a bien aidé grâce au binding bidirectionnel. Le binding bidirectionnel permet à ce que la valeur d’une variable du modèle soit toujours la même que celle du formulaire. Autrement dit, si l’utilisateur change d’attribution (de risque ou de situation), elle change directement dans le modèle.

En sachant cela, nous avons construit un modèle objet avec nos quatre objets (catégories, situations, risques, mesures) imbriqués.

Ainsi si on part de la liste des situations d’une catégorie, on peut par exemple lister l’ensemble des situations et des risques associés à chacune comme ceci :

<form (ngSubmit)="onSubmit()">
   <div *ngFor="let situation of situations;">
       <input type="text" [(ngModel)]="situation.nom">
       <tr *ngFor="let risque of situation.risques;">
   	     <textarea [(ngModel)]="risque.nom" type="text"></textarea>

Dans cet exemple, nous créons un formulaire et nous parcourons la variable situations qui contient plusieurs situation, pour chacune de ces situation l’utilisateur peut éditer son nom. Ensuite nous parcourons tous les risques associés à cette situation et de la même manière et l’utilisateur peut modifier son nom. En parallèle aux actions de l’utilisateur, le modèle se met à jour.

Si l’utilisateur veut insérer plusieurs risques dans une situation, nous avons ajouté un bouton qui au clic ajoute dans le modèle une nouvelle entité risque ce qui modifie l’objet situations qui contient notamment un tableau de Risque, et Angular reparcours automatiquement les boucles et affiche une nouvelle balise textarea avec le nouveau risque. Le tout de manière dynamique, extrêmement rapidement et sans rechargement de page. Au top !

Voici le rendu que nous obtenons dans notre application :

Génération d’un PDF à l’aide de la librairie Html2Pdf

Une fois les tableaux précédents créés sur la plateforme, notre client souhaitait pouvoir les exporter au format PDF. Pour effectuer cette exportation et ne pas avoir à recréer tout le tableau dans notre PDF avec les librairies classiques comme FPDF ou TCPDF, nous avons opté pour une librairie qui permet de convertir des éléments HTML et CSS en PDF : Html2Pdf.

Cette libraire s’utilise très simplement, il faut créer un objet Html2Pdf, appeler la méthode writeHTML à laquelle on passe une vue avec ses paramètres.

Enfin, on appelle la méthode Output avec le nom donné à notre PDF et le code de la méthode de rendu du document : ‘D’ pour le télécharger, ‘S’ pour le renvoyer sous forme d’une chaîne de caractères.

$html2pdf = new Html2Pdf();
        
//Appel d'une vue représentant le contenu du PDF
$html2pdf->writeHTML(view('printPDF', ['duerp'=> $duerp, 'etablissement'=>$etablissement]));

//D pour forcer le téléchargement
$pdf= $html2pdf->Output('duerp.pdf', 'D');

return $pdf;

Attention cependant, la librairie n’est pas optimisée pour les longs fichiers et les durées de créations peuvent rapidement s’allonger…