Gestion des utilisateurs

Profile

Temps estimé :5 minutes 35 views

ProfileService : pour les appels API centralisés.Pinia Store : pour la gestion des données des profils (CRUD).Modals (AddProfileModal et EditProfileModal) : pour l’ajout et l’édition des profils.TrueProfileManagement : composant parent pour la gestion des profils.Loaders : pour charger les données annexes comme les équipes et les catégories.Pagination : pour gérer l’affichage des données volumineuses.API Format : pour formater les réponses de l’API.

Documentation Illustrée du Module de Gestion des Profils

Ce tutoriel vous guide à travers la création d’un module de gestion des profils dans une application Vue.js. Le but est de vous montrer le raisonnement derrière chaque étape, tout en expliquant comment nous avons structuré et implémenté les différentes fonctionnalités, notamment la gestion des utilisateurs, des rôles, des catégories, et des relations complexes.

Le module repose sur Vue.js, Pinia pour la gestion d’état, Axios pour les appels API, et Vee-Validate pour la gestion des formulaires.


Architecture Globale

  • ProfileService : pour les appels API centralisés.
  • Pinia Store : pour la gestion des données des profils (CRUD).
  • Modals (AddProfileModal et EditProfileModal) : pour l’ajout et l’édition des profils.
  • TrueProfileManagement : composant parent pour la gestion des profils.
  • Loaders : pour charger les données annexes comme les équipes et les catégories.
  • Pagination : pour gérer l’affichage des données volumineuses.
  • API Format : pour formater les réponses de l’API.

1. Création du Service :

ProfileService

Le ProfileService est responsable des appels API liés à la gestion des profils. Il centralise toutes les interactions avec le serveur, ce qui permet de rendre le code plus maintenable et réutilisable.

import axios from 'axios';

class ProfileService {
  async getAll(query: string) {
    return axios.get(`/api/user/user?${query}`);
  }

  async getById(id: string) {
    return axios.get(`/api/user/user/${id}?include=field_image`);
  }

  async post(url: string, payload: any) {
    return axios.post(url, payload);
  }

  async update(url: string, id: string, payload: any) {
    return axios.patch(`${url}/${id}`, payload);
  }

  async delete(id: string) {
    return axios.delete(`/api/user/user/${id}`);
  }

  async uploadImage(url: string, image: File) {
    const formData = new FormData();
    formData.append('file', image);
    return axios.post(url, formData);
  }
}

export default new ProfileService();

Explication :

  • getAll, getById : récupèrent tous les profils ou un profil spécifique.
  • post, update : ajoutent ou modifient un profil.
  • delete : supprime un profil.
  • uploadImage : télécharge l’image de profil.

2. Le Store Pinia :

Gestion des États

Le store Pinia centralise la gestion de l’état des profils, les erreurs, et les actions CRUD.

import { defineStore } from "pinia";
import ProfileService from "@/services/ProfileService";

export const useTrueProfileStore = defineStore("trueprofile", () => {
  const profiles = ref([]);
  const errors = ref({});
  
  // Actions CRUD
  const getAllProfiles = async (params: any) => {
    try {
      const response = await ProfileService.getAll(params);
      profiles.value = response.data;
    } catch (error) {
      errors.value = error;
    }
  };

  const addProfile = async (profileData: any) => {
    try {
      const response = await ProfileService.post('api/user/user', profileData);
      profiles.value.push(response.data);
    } catch (error) {
      errors.value = error;
    }
  };

  return {
    profiles,
    getAllProfiles,
    addProfile,
    // ... autres actions
  };
});

Explication :

  • getAllProfiles : récupère tous les profils avec pagination.
  • addProfile : ajoute un nouveau profil.
  • editProfile, deleteProfile : gèrent la modification et la suppression des profils.

:value= »true »

:unchecked-value= »false »

3. Modals :

AddProfileModal et EditProfileModal

Les modals permettent d’ajouter et de modifier des profils sans changer de page.

<!-- src/components/modals/EditProfileModal.vue -->
<template>
  <div class="modal">
    <form @submit.prevent="submit">
      <input v-model="profile.first_name" placeholder="Prénom" />
      <input v-model="profile.last_name" placeholder="Nom" />
      <input v-model="profile.email" placeholder="Email" />
      <button type="submit">Modifier</button>
    </form>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import { useTrueProfileStore } from "@/stores/trueprofile";
const profileStore = useTrueProfileStore();

const profile = ref({
  first_name: "",
  last_name: "",
  email: ""
});

const submit = async () => {
  await profileStore.editProfile(profile.value);
};
</script>

Explication :

  • Le modal utilise un formulaire simple avec des champs pré-remplis à l’aide du profileStore.
  • Vee-Validate est utilisé pour valider les champs, et les données sont envoyées via submit.

4. Le Composant Parent :

TrueProfileManagement

Ce composant est responsable de l’affichage des profils et des actions globales comme l’ouverture des modals.

5. Les Loaders : Équipes et Catégories

Les loaders facilitent le chargement des données annexes telles que les équipes et les catégories. Ces données peuvent être réutilisées dans plusieurs composants.

// src/loaders/equipeLoader.ts
import { ref } from "vue";
import { useTrueProfileStore } from "@/stores/trueprofile";

export function useEquipeLoader() {
  const equipes = ref([]);
  const loadEquipes = async () => {
    const profileStore = useTrueProfileStore();
    equipes.value = await profileStore.getEquipes();
  };

  return {
    equipes,
    loadEquipes
  };
}

Explication :

  • Le loader charge les données des équipes en faisant appel au store des profils.
  • Cette approche permet de réutiliser les loaders dans différents composants, sans dupliquer la logique de chargement.

6. API Format : Formatage des Données

Le formatage des données API permet de rendre les réponses du backend directement utilisables par l’interface utilisateur.

// src/apiformat/profileFormat.ts
export const formatProfileData = (response: any) => {
  return response.data.map((item: any) => ({
    id: item.id,
    first_name: item.attributes.field_firstname,
    last_name: item.attributes.field_lastname,
    email: item.attributes.mail,
    role: item.attributes.field_account,
    bio: item.attributes.field_bio
  }));
};

7. Pagination

La pagination permet de diviser les résultats en plusieurs pages pour améliorer les performances.

// src/apiformat/Pagination.ts
export default class Pagination {
  currentPage = 1;
  itemsPerPage = 10;
  totalItems = 0;

  constructor(totalItems = 0, currentPage = 1, itemsPerPage = 10) {
    this.totalItems = totalItems;
    this.currentPage = currentPage;
    this.itemsPerPage = itemsPerPage;
  }

  get queryString() {
    return `page[offset]=${(this.currentPage - 1) * this.itemsPerPage}&page[limit]=${this.itemsPerPage}`;
  }
}
CONTENTS