1. Ajoutez les appels à l’API
Remplacez le contenu de src/api.js par ce fichier. Le navigateur appelle toujours le chemin local /odoo-api/training/api/notes. La configuration Vite s’occupe ensuite de joindre Odoo et d’ajouter la clé.
const NOTES_API_URL = "/odoo-api/training/api/notes";
async function readResponse(response) {
let payload;
try {
payload = await response.json();
} catch {
throw new Error(`Odoo a répondu avec le statut ${response.status}, sans JSON lisible.`);
}
if (!response.ok) {
const message = payload?.error?.message || `La requête a été refusée (${response.status}).`;
throw new Error(message);
}
return payload;
}
function isNote(value) {
return Number.isInteger(value?.id)
&& typeof value.title === "string"
&& typeof value.body === "string";
}
function assertNotesContract(payload) {
if (!Array.isArray(payload?.notes)
|| !Number.isInteger(payload.count)
|| payload.count !== payload.notes.length
|| !payload.notes.every(isNote)) {
throw new Error("La réponse d'Odoo ne respecte pas le contrat notes + count.");
}
return payload;
}
export async function fetchNotes() {
const response = await fetch(NOTES_API_URL, {
headers: { Accept: "application/json" },
});
return assertNotesContract(await readResponse(response));
}
export async function createNote({ title, body }) {
const response = await fetch(NOTES_API_URL, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({ title, body }),
});
const payload = await readResponse(response);
if (!isNote(payload?.note)) {
throw new Error("La réponse de création ne contient pas la note attendue.");
}
return payload.note;
}fetchNotes() lit la liste. readResponse() transforme la réponse JSON et affiche une erreur claire si Odoo refuse la requête. La fonction createNote() servira à l’étape suivante.
2. Affichez la liste
Remplacez maintenant le contenu de src/App.vue. Quand Vue ouvre la page, onMounted(loadNotes) lance la lecture. Le bouton Actualiser relance la même fonction.
<script setup>
import { onMounted, ref } from "vue";
import { fetchNotes } from "./api.js";
const notes = ref([]);
const count = ref(0);
const loading = ref(false);
const error = ref("");
async function loadNotes() {
loading.value = true;
error.value = "";
try {
const payload = await fetchNotes();
notes.value = payload.notes;
count.value = payload.count;
} catch (requestError) {
error.value = requestError.message;
} finally {
loading.value = false;
}
}
onMounted(loadNotes);
</script>
<template>
<main class="page-shell">
<header class="page-header">
<p class="eyebrow">Client Vue 3 · API Odoo locale</p>
<h1>Notes de formation</h1>
<p>Cette interface lit les mêmes notes que l'application Odoo du Jour 2.</p>
</header>
<p v-if="error" class="message error" role="alert">{{ error }}</p>
<section class="panel" aria-labelledby="notes-title" aria-live="polite">
<div class="section-heading">
<h2 id="notes-title">Notes enregistrées</h2>
<button type="button" class="secondary" :disabled="loading" @click="loadNotes">
{{ loading ? "Chargement…" : "Actualiser" }}
</button>
</div>
<p v-if="!loading && notes.length === 0">Odoo n'a renvoyé aucune note.</p>
<ul v-else class="notes-list">
<li v-for="note in notes" :key="note.id">
<h3>{{ note.title }}</h3>
<p>{{ note.body }}</p>
<small>Identifiant {{ note.id }}</small>
</li>
</ul>
<p class="count">Nombre annoncé par l'API : {{ count }}</p>
</section>
</main>
</template>Les valeurs notes, count, loading et error sont l’état de la page. Quand elles changent, Vue met à jour l’écran. Vous n’avez rien d’autre à faire pour rafraîchir la liste.
3. Regardez le résultat
- Enregistrez les deux fichiers.
- Avec Odoo et Vite en marche, ouvrez
http://127.0.0.1:5173. - Retrouvez les notes créées au Jour 2.
- Cliquez sur Actualiser : la liste est relue sans recharger toute la page.
Si la clé est absente ou invalide, la page affiche l’erreur renvoyée par Odoo. Si aucune note n’existe encore, elle affiche simplement Odoo n’a renvoyé aucune note.
4. Suivez la requête une fois
Ouvrez les outils de développement du navigateur, puis l’onglet Réseau. Vous verrez une requête vers /odoo-api/training/api/notes. La clé n’apparaît pas dans cette requête du navigateur : Vite l’ajoute seulement lorsqu’il la transmet à Odoo.
Vue affiche une liste, Vite la transmet à Odoo, puis Odoo lit training.note avec l’ORM et renvoie du JSON. Les données restent les mêmes que dans l’interface Odoo du Jour 2.