Imprimer
Catégorie : R3.01 - dev. Web côté client (vuejs)
Affichages : 1201

Préambule

L'objectif principal de ce TP est d'implémenter une pseudo application bancaire et de compléter l'application générale DrMad, afin de mettre en oeuvre le principe des slots. Il y a donc un scénario à deux niveaux.

Le scénario principal est le suivant :

 

Le scénario d'utilisation de la boutique est quasi le même que celle du TP 4. Les différences sont :

 

Le scénario pour utiliser la banque est le suivant :

 

 

 

 

 

Télécharger la vidéo de démonstration des scénarii : [ vuejs-scenario-TP5.mkv ]

 

 

 

0°/ Mise en place

La structuration générale reste la même que pour les TPs précédents. De plus, certains composants vont être réutilisés. La mise en place initiale la plus simple consiste donc à :

 

1°/  Modifications sur App et la boutique

 

Dans le TP4, les boutons de la boutique se trouvent dans une NavBar, elle même dans le template de App. Il suffit de tout déplacer dans ShopView. D'après les scénarios ci-dessus, App ne contient au final qu'une NavBar avec deux boutons permettant soit d'afficher l'accueil de la boutique, soit de la banque. 

Comme le comportement de NavBar va être modifié (cf. section 4), le bouton Logout de la boutique pose problème. En effet, dans le TP4, c'est App qui décide quoi faire quand on clique sur un bouton. Dans ce TP, c'est NavBar qui suit une route quand on clique sur un bouton. Or, suivre une route consiste à afficher un composant et pas exécuter du code, en l'occurrence appeler l'action de shop.js qui fait le logout. A vous de trouver un moyen pour appeler cette action.

Pour payer une commande, il faut fournir un uuid de transaction bancaire. Cela impose des changements dans plusieurs fichiers :

 

2°/ Ajout des services liés à la banque

Le principe reste le même que dans les TP précédents. On crée des fonctions (cf. liste ci-dessous) dans datasource/controller.js pour manipuler les données de la source locale (dans data.js) liées à la banque. Les fonctions de service sont placées dans services/bankaccount.service.js. dans lequel il suffit d'jaouter une paire de fonction pour chaque service :

Remarque : il est conseillé d'utiliser les règles de nommage des fonctions principales et secondaires déjà utilisées lors des TPs précédents.

Exemple pour récupérer les informations d'un compte : la fonction principale getAccount(number) appelle la fonction secondaire getAccountFromLocalSource(number), qui elle-même appelle la fonction getAccount(number) de controller.js.

 

Rappel : les fonctions de controller.js doivent retourner un résultat avec une structure qui doit être identique à celle retournée par l'API. Pour rappel, cette structure est du type {error: num_erreur, status: ..., data: ...}. S'il y a une erreur, data contient le message d'erreur. Sinon, data contient un objet dont la structure dépend du type de requête.

 

Voici la liste des fonctions à définir dans controller.js pour gérer la banque à partir de la source de données locale, avec le descriptif de ce qu'elles retournent :

 

 

 

 

 Attention !

Dans le tableau transactions de data.js, les objets transaction ont un champ date qui est un objet, contenant lui-même un champ $date avec la vraie date. Cela implique que :

  • pour comparer la date de deux objets transaction t1 et t2, il faut utiliser quelque chose du genre if (t1.date.$date === t2.date.$date) ...
  • quand on crée une nouvelle transaction, il FAUT utiliser le même format.

Les objets transaction ont également un champ account, qui référence le champ _id d'un compte bancaire et pas le numéro de compte (= champ number)

  

Après avoir écrit des fonctions, il faut créer les fonctions de service associées dans services/bankaccount.servce.js, en utilisant le principe des TPs précédents, à savoir ajouter une paire de fonction pour chaque service :

Remarque : il est conseillé d'utiliser les règles de nommage des fonctions principales et secondaires déjà utilisées lors des TPs précédents.

Exemple pour récupérer les informations d'un compte : la fonction principale getAccount(number) appelle la fonction secondaire getAccountFromLocalSource(number), qui elle-même appelle la fonction getAccount(number) de controller.js.

 

3°/ Modification du store

Dans le TP 3, le store a déjà été modularisé avec un fichier bank.js qui représente le module concernant la banque. Cependant, ce qui a été mis en place dans les TPs précédents n'est pas totalement adapté au sujet présent. Il faut donc modifier ce module afin de prendre en compte  les fonctionnalités demandées :

 

4°/ La barre de navigation

 L'objectif est de modifier NavBar.vue pour en faire un composant utilisant les props et les scoped-slot pour le rendre facilement paramétrable par le composant parent. De plus, NavBar n'envoie plus un signal au parent pour signaler qu'un des boutons a été cliqué : il suit directement une route de vue-router donnée via une props.

On obtient quelque chose du genre :

<button v-for="(link, index) in links" :key="index" ... >
  <slot name="nav-button" :label="link.label" >{{link.label}}</slot>
</button>

 

  • Il faut ensuite ajouter la gestion des clics sur les boutons :
    • en cas de clic, on appelle une fonction goTo(dest), définie dans methods, avec comme paramètre dest la valeur de link.to.
    • la fonction goTo() suit la route donnée en paramètre.

 

Pour mettre en place la barre de navigation principale, il faut modifier App.vue pour indiquer à NavBar.vue le contenu du slot pour chaque bouton :

  • passer comme valeur de la props links le tableau [ { label: "boutique", to: "/shop"}, { label: "banque", to: "/bank"} ],
  • pour le premier bouton, donner comme contenu au slot le mot "boutique" écrit en gras
  • pour le deuxième bouton, donner comme contenu au slot une icône ressemblant à une banque.

Remarques :

  • dans une application vue, les ressources de type icônes se trouvent généralement dans le sous-répertoire assets.
  • une fois placées dans ce répertoire, on peut facilement y faire référence via un chemin d'accès

Exemple :

<template>
  <div>
    <img src="/@/assets/myicon.png">
    ...
  </div>
</template>

 

5°/ Un menu vertical

 

6°/ Le composant racine de la banque

[ {type: "title", label: "Opérations"}, {type: "link", label: "Solde", to: "/bank/amount"}, {type: "link", label: "Débit/Virement", to: "/bank/operation"}, {type: "title", label: "États"} , {type: "link", label: "Historique", to: "/bank/history"}  ]

 

 

7°/ L'accueil de la banque

 

8°/ Afficher le solde

 

 

9°/ Débit & virements

 

10°/ Un tableau dynamique avec case à cocher

L'objectif est de faire un composant DataTable.vue, utilisant les props items, headers, itemCheck, itemButton, tableButton ainsi que slots (cf. description ci-dessous) pour le rendre facilement paramétrable par le composant parent.

Ce composant permet d'afficher :

Pour qu'un composant parent fournisse des données à DataTable, il doit respecter une structure stricte concernant les props headers et items :

Par ailleurs, les clics sur :

 

Exemple d'utilisation dans un composant parent qui veut afficher une table avec 4 colonnes (1 pour les cases à cocher, 2 pour les champs de chaque item, 1 pour les boutons), ainsi qu'un bouton après la table. Il y a 4 lignes (1 pour l'entête, 3 pour les données). A noter que dans cet exemple, on ne capture aucun des événements :

<template>
  ...
  <DataTable :headers="headers" :items="items" itemCheck itemButton tableButton></DataTable>
  ...
</template>
<script>
  ...
  data: () => ({
    headers : [ {label: "nom", name: "virus"}, { label: "prix", name: "price"} ],
    items: [
      { virus: "grippe", price: 1000, strength: 5 }, // NB: strength ne sera pas visualisé dans DataTable car headers ne le mentionne pas
      { virus: "covid", price: 150, strength: 5 },
      { virus: "cholera", price: 6666, strength: 20 },
    ]
  })
  ...
</script>

 

11°/ L'historique des transactions

  • Dans le répertoire views, créer un composant BankHistory.vue.
  • Ce composant affiche :
    • un titre, qui est par défaut "Opérations passées", mais qui peut être changé via un slot
    • une case à cocher avec comme label "Filtrer par période", suivie de deux champs de saisie qui n'apparaissent que si la case est cochée, avec comme labels respectifs "Du", "Au".
    • un composant DataTable, contenant des transactions associées au compte courant. Par défaut, elles sont toutes affichées sauf si le filtrage est actif.
    • Que le filtrage soit actif ou non, les transactions passées sont classées par order chronologique décroissant, donc avec les plus récentes en premier.

 

  • Le comportement du filtrage est le suivant :
    • si seul le premier champ est rempli, on sélectionne toutes les transactions à partir de cette date,
    • si seul le deuxième champ est rempli, on sélectionne toutes les transactions jusqu'à cette date,
    • si les deux champs sont remplis, on sélectionne les transactions entre les deux dates.
    • si le premier champ est déjà rempli, et que l'on tape une date antérieure dans le second champ, ce dernier est vidé puisque invalide.
    • si le deuxième champ est déjà rempli, et que l'on tape une date postérieure dans le premier champ, ce dernier est vidé puisque invalide.
    • dès que l'on valide la saisie d'un des champs, le filtrage doit se faire et donc impacter l'affichage de la table.

 

  • La table doit afficher :
    • 1 colonne avec des cases à cocher,
    • 1 colonne avec le montant des transactions,
    • 1 colonne  avec la date des transactions,
    • 1 colonne avec une lettre, qui doit être S si le compte courant est la source de la transaction (= montant négatif) et D si elle est la destination (= montant positif).
    • 1 colonne avec des boutons, dont le label est "Détails"
    • 1 bouton après la table avec comme label "Voir".

 

  • Quand une des boutons d'item est cliqué, une boite de dialogue s'ouvre avec dedans l'uuid de la transactions.
  • Quand le bouton d'après table est cliqué, une boite de dialogue s'ouvre avec dedans l'uuid de toutes les transactions dont la case est cochée.

 

12°/ Déconnexion

  • Dans le répertoire views, créer un composant BankLogout.vue.
  • Ce composant affiche simplement un texte signifiant la déconnexion, puis au bout de 1 seconde, utilise la mutation de bank.js pour "effacer" le compte courant et ensuite rediriger vers l'accueil de la banque.
  • NB : il faut que l'attente et la redirection se fasse sans intervention de l'utilisateur.