# Séance 3 : Communication avec API

## 🎯 Objectifs

* Appeler une API externe.
* Gérer erreurs, loaders et services dédiés.

## 📖 Partie théorique

### Architecture client/serveur

* Vue/Nuxt côté client, API côté serveur.
* Communication via HTTP (REST, JSON, voire GraphQL).

### Fetch API vs Axios

#### Fetch

* `fetch` : natif, simple, mais moins de fonctionnalités.

**Exemple :**

```javascript
fetch('http://localhost:3001/tasks')
  .then(response => response.json())
  .then(data => {
    console.log(data);
  });
```

#### Axios

* `axios` : plus complet, gestion des interceptors, requêtes simplifiées.

**Exemple :**

```javascript
import axios from 'axios';

axios.get('http://localhost:3001/tasks')
  .then(response => {
    console.log(response.data);
  });
```

### Gestion des erreurs

* Utilisation de `try/catch` pour capturer les erreurs réseau ou API.

**Exemple avec Fetch :**

```javascript
async function fetchTasks() {
  try {
    const response = await fetch('http://localhost:3001/tasks');
    if (!response.ok) {
      throw new Error('Erreur lors de la récupération des tâches');
    }
    const data = await response.json();
    console.log(data);
  } catch (error) {
    // Affichage d’un message d’erreur à l’utilisateur
    alert('Une erreur est survenue : ' + error.message);
  }
}
```

Dans cet exemple, si la requête échoue (problème réseau, serveur indisponible, etc.), le bloc `catch` permet d’afficher un message d’erreur à l’utilisateur.

**Exemple simple en Vue.js :**

```javascript
<template>
  <div>
    <button @click="fetchTasks">Charger les tâches</button>
    <div v-if="errorMessage" class="error">
      {{ errorMessage }}
    </div>
    <ul v-if="tasks.length">
      <li v-for="task in tasks" :key="task.id">{{ task.title }}</li>
    </ul>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const tasks = ref([])
const errorMessage = ref('')

async function fetchTasks() {
  errorMessage.value = ''
  try {
    const response = await fetch('http://localhost:3001/tasks')
    if (!response.ok) {
      throw new Error('Erreur lors de la récupération des tâches')
    }
    tasks.value = await response.json()
  } catch (error) {
    errorMessage.value = 'Une erreur est survenue : ' + error.message
  }
}
</script>

<style>
.error {
  color: red;
  margin: 1em 0;
}
</style>
```

Cet exemple affiche un message d’erreur à l’utilisateur si la récupération des tâches échoue.

### Loaders

Pour afficher un loader pendant l'appel à l'API, il suffit d'ajouter une variable d'état `isLoading` et de l'utiliser dans le template :

```javascript
<template>
  <div>
    <button @click="fetchTasks">Charger les tâches</button>
    <div v-if="isLoading" class="loader">Chargement...</div>
    <div v-if="errorMessage" class="error">
      {{ errorMessage }}
    </div>
    <ul v-if="tasks.length && !isLoading">
      <li v-for="task in tasks" :key="task.id">{{ task.title }}</li>
    </ul>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const tasks = ref([])
const errorMessage = ref('')
const isLoading = ref(false)

async function fetchTasks() {
  errorMessage.value = ''
  isLoading.value = true
  try {
    const response = await fetch('http://localhost:3001/tasks')
    if (!response.ok) {
      throw new Error('Erreur lors de la récupération des tâches')
    }
    tasks.value = await response.json()
  } catch (error) {
    errorMessage.value = 'Une erreur est survenue : ' + error.message
  } finally {
    isLoading.value = false
  }
}
</script>

<style>
.loader {
  color: #007bff;
  font-weight: bold;
  margin: 1em 0;
}
.error {
  color: red;
  margin: 1em 0;
}
</style>
```

Ici, le loader s'affiche tant que la requête est en cours (`isLoading` à `true`), puis disparaît dès que la réponse est reçue ou qu'une erreur survient.

### Services dédiés

* Création d'un service API pour centraliser les appels HTTP.

## 📝 Travaux pratiques

### Étape 1 : Installation de JSON Server

JSON Server permet de créer une API REST complète à partir d'un simple fichier JSON.

**Installation :**

```bash
# Installation globale
npm install -g json-server

# Ou installation locale dans le projet
npm install --save-dev json-server
```

### Étape 2 : Création du fichier de données

**Créer `db.json` à la racine du projet :**

```json
{
  "tasks": [
    {
      "id": 1,
      "title": "Apprendre Vue 3",
      "description": "Maîtriser la Composition API et les nouveautés",
      "priority": "High",
      "completed": false,
      "createdAt": "2024-09-01T10:00:00Z",
      "dueDate": "2024-09-30T23:59:59Z"
    },
    {
      "id": 2,
      "title": "Créer un projet",
      "description": "Développer une application de gestion de tâches",
      "priority": "Medium",
      "completed": true,
      "createdAt": "2024-09-15T14:30:00Z",
      "dueDate": "2024-10-15T23:59:59Z"
    },
    {
      "id": 3,
      "title": "Déployer l'application",
      "description": "Mettre en ligne sur Netlify ou Vercel",
      "priority": "Low",
      "completed": false,
      "createdAt": "2024-09-20T09:15:00Z",
      "dueDate": "2024-11-01T23:59:59Z"
    }
  ],
  "users": [
    {
      "id": 1,
      "name": "Alice Dupont",
      "email": "alice@example.com",
      "role": "admin"
    },
    {
      "id": 2,
      "name": "Bob Martin",
      "email": "bob@example.com",
      "role": "user"
    }
  ]
}
```

### Étape 3 : Configuration et démarrage de JSON Server

**Ajouter les scripts dans `package.json` :**

```json
{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "api": "json-server --watch db.json --port 3001"
  }
}
```

**Pour exécuter simultanément Vue et l'API :**

```bash
# Terminal 1 : Vue
npm run dev

# Terminal 2 : API JSON Server
npm run api
```

### Étape 4 : URLs disponibles

Une fois JSON Server démarré sur le port 3001, les endpoints suivants sont disponibles :

**Endpoints automatiques :**

```
GET    /tasks           # Récupérer toutes les tâches
GET    /tasks/1         # Récupérer la tâche avec l'ID 1
POST   /tasks           # Créer une nouvelle tâche
PUT    /tasks/1         # Mettre à jour la tâche avec l'ID 1
PATCH  /tasks/1         # Mise à jour partielle de la tâche avec l'ID 1
DELETE /tasks/1         # Supprimer la tâche avec l'ID 1

GET    /users           # Récupérer tous les utilisateurs
GET    /users/1         # Récupérer l'utilisateur avec l'ID 1
```

**Paramètres de requête supportés :**

```
GET /tasks?completed=true           # Filtrer par statut
GET /tasks?priority=High            # Filtrer par priorité
GET /tasks?_sort=createdAt&_order=desc  # Trier par date (desc)
GET /tasks?_limit=10&_page=2        # Pagination
GET /tasks?q=Vue                    # Recherche textuelle
```

### Étape 5 : Appels API dans Vue

* Utilisez ces API pour lier vos tâches dans votre application Vue.
* Gérez les états de chargement et d'erreur avec des loaders et des messages.
* Créez des services dédiés pour organiser vos appels API.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://cours.davidannebicque.fr/vue.js-but/but3/seance-3-communication-avec-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
