<aside> 💡

Exercice 3

Implémenter la modification d’un parcours

</aside>

Passons à la modification des parcours.

Ajout du hook pour modifier les parcours

src/features/parcours/hooks/useUpdateParcours.tsx

import { useMutation, useQueryClient } from "@tanstack/react-query"
import { apiFetch } from "@/lib/api"
import type { Parcours, UpdateParcoursPayload } from "../types"

interface UpdateParcoursResponse {
  message: string;
  parcours: Parcours;
}

export const useUpdateParcours = () => {
  const queryClient = useQueryClient()

  return useMutation({
    mutationFn: async ({
      id,
      payload,
    }: {
      id: number;
      payload: UpdateParcoursPayload;
    }): Promise<Parcours> => {
      const response = await apiFetch(`/parcours/${id}`, {
        method: "PUT",
        body: JSON.stringify(payload),
      })

      if (!response.ok) {
        const error = await response.json()
        throw new Error(error.error || "Failed to update parcours")
      }

      const data = (await response.json()) as UpdateParcoursResponse
      return data.parcours
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["parcours"] })
    },
  })
}

Intégration du composant d’édition

Depuis le listing des parcours, nous avons déjà ajouter un bouton permettant d’ouvrir une modal pour la création d’un parcours, adaptons cette dernière afin de la ré-utiliser pour l’édition de notre parcours.

<aside> ❗

Nous avons utilisée le hook useEffect dans ce composant. Ce hook provient de React et permet d’effectuer des actions après que le composant a été “monté/render”. À la fin de celui un tableau est donné, celui-ci permet d’indiquer:

Désormais nous avons notre composant et l’objectif est de l’intégrer à notre page de listing, là où est présent le tableau.

<aside> ❓

Pourquoi avoir créer un nouveau composant pour la modal ?

</aside>

Cela permet de séparer le code, apportant clarté et maintenabilité. Bien entendu vous pouvez avoir un simple fichier qui contient toutes les pages, tous les composants. Cependant il est bien plus simple d’utiliser plusieurs dossiers structuré de la même manière en petits sous-dossiers et fichiers, plutôt que de gros fichiers de milliers de lignes dur à maintenir!

Modification du composant Table

Modifier le type de key afin qu’il accepte aussi des strings n’étant pas présent dans notre jeu de donnée. Cela va permettre d’ajouter les colonnes que l’on souhaite, comme des actions par exemple!

type Props<TData extends Record<string, any>> = {
  data?: TData[]
  columns: {
    // keyof TData signifie que l'on sait que ça 
    // les clés possibles proviennent de l'objet
    // l'ajout de | string permet d'informer que n'importe
    // quel string est possible.
    // L'ajout de & {} permet de garder l'auto-complétion, petit hack TS.
    key: keyof TData | (string & {})
    label: string
    render?: (data: TData) => ReactNode
  }[]
  onRowClick?: (row: TData) => void
}