From f29f90a16f1dd87d7112fe8a9af39e7afdaf8762 Mon Sep 17 00:00:00 2001 From: gilles Date: Sun, 22 Feb 2026 04:10:16 +0100 Subject: [PATCH] feat(frontend): API layer + stores Pinia Ajoute le client Axios, les modules API (gardens, varieties, plantings, tasks) et les stores Pinia correspondants. Corrige tsconfig.json pour inclure vite/client et DOM.Iterable. Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/api/client.ts | 5 ++++ frontend/src/api/gardens.ts | 49 ++++++++++++++++++++++++++++++++ frontend/src/api/plantings.ts | 31 ++++++++++++++++++++ frontend/src/api/tasks.ts | 20 +++++++++++++ frontend/src/api/varieties.ts | 23 +++++++++++++++ frontend/src/stores/gardens.ts | 27 ++++++++++++++++++ frontend/src/stores/plantings.ts | 27 ++++++++++++++++++ frontend/src/stores/tasks.ts | 34 ++++++++++++++++++++++ frontend/src/stores/varieties.ts | 27 ++++++++++++++++++ frontend/tsconfig.json | 3 +- 10 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 frontend/src/api/client.ts create mode 100644 frontend/src/api/gardens.ts create mode 100644 frontend/src/api/plantings.ts create mode 100644 frontend/src/api/tasks.ts create mode 100644 frontend/src/api/varieties.ts create mode 100644 frontend/src/stores/gardens.ts create mode 100644 frontend/src/stores/plantings.ts create mode 100644 frontend/src/stores/tasks.ts create mode 100644 frontend/src/stores/varieties.ts diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts new file mode 100644 index 0000000..5e09632 --- /dev/null +++ b/frontend/src/api/client.ts @@ -0,0 +1,5 @@ +import axios from 'axios' + +export default axios.create({ + baseURL: import.meta.env.VITE_API_URL ?? '', +}) diff --git a/frontend/src/api/gardens.ts b/frontend/src/api/gardens.ts new file mode 100644 index 0000000..1620b93 --- /dev/null +++ b/frontend/src/api/gardens.ts @@ -0,0 +1,49 @@ +import client from './client' + +export interface Garden { + id?: number + nom: string + description?: string + type: string + latitude?: number + longitude?: number + adresse?: string + exposition?: string + ombre?: string + sol_type?: string + grille_largeur: number + grille_hauteur: number +} + +export interface GardenCell { + id?: number + garden_id?: number + col: number + row: number + libelle?: string + etat: string + notes?: string +} + +export interface Measurement { + id?: number + garden_id?: number + temp_air?: number + temp_sol?: number + humidite_air?: number + humidite_sol?: number + source?: string + ts?: string +} + +export const gardensApi = { + list: () => client.get('/api/gardens').then(r => r.data), + get: (id: number) => client.get(`/api/gardens/${id}`).then(r => r.data), + create: (g: Partial) => client.post('/api/gardens', g).then(r => r.data), + update: (id: number, g: Partial) => client.put(`/api/gardens/${id}`, g).then(r => r.data), + delete: (id: number) => client.delete(`/api/gardens/${id}`), + cells: (id: number) => client.get(`/api/gardens/${id}/cells`).then(r => r.data), + measurements: (id: number) => client.get(`/api/gardens/${id}/measurements`).then(r => r.data), + addMeasurement: (id: number, m: Partial) => + client.post(`/api/gardens/${id}/measurements`, m).then(r => r.data), +} diff --git a/frontend/src/api/plantings.ts b/frontend/src/api/plantings.ts new file mode 100644 index 0000000..66a177d --- /dev/null +++ b/frontend/src/api/plantings.ts @@ -0,0 +1,31 @@ +import client from './client' + +export interface Planting { + id?: number + garden_id: number + variety_id: number + cell_id?: number + date_plantation?: string + quantite: number + statut: string + notes?: string +} + +export interface PlantingEvent { + id?: number + planting_id?: number + type: string + note?: string + ts?: string +} + +export const plantingsApi = { + list: () => client.get('/api/plantings').then(r => r.data), + get: (id: number) => client.get(`/api/plantings/${id}`).then(r => r.data), + create: (p: Partial) => client.post('/api/plantings', p).then(r => r.data), + update: (id: number, p: Partial) => client.put(`/api/plantings/${id}`, p).then(r => r.data), + delete: (id: number) => client.delete(`/api/plantings/${id}`), + events: (id: number) => client.get(`/api/plantings/${id}/events`).then(r => r.data), + addEvent: (id: number, e: Partial) => + client.post(`/api/plantings/${id}/events`, e).then(r => r.data), +} diff --git a/frontend/src/api/tasks.ts b/frontend/src/api/tasks.ts new file mode 100644 index 0000000..c872289 --- /dev/null +++ b/frontend/src/api/tasks.ts @@ -0,0 +1,20 @@ +import client from './client' + +export interface Task { + id?: number + titre: string + description?: string + garden_id?: number + priorite: string + echeance?: string + statut: string +} + +export const tasksApi = { + list: (params?: { statut?: string; garden_id?: number }) => + client.get('/api/tasks', { params }).then(r => r.data), + get: (id: number) => client.get(`/api/tasks/${id}`).then(r => r.data), + create: (t: Partial) => client.post('/api/tasks', t).then(r => r.data), + update: (id: number, t: Partial) => client.put(`/api/tasks/${id}`, t).then(r => r.data), + delete: (id: number) => client.delete(`/api/tasks/${id}`), +} diff --git a/frontend/src/api/varieties.ts b/frontend/src/api/varieties.ts new file mode 100644 index 0000000..ce89c68 --- /dev/null +++ b/frontend/src/api/varieties.ts @@ -0,0 +1,23 @@ +import client from './client' + +export interface PlantVariety { + id?: number + nom_commun: string + nom_botanique?: string + variete?: string + famille?: string + type_plante?: string + besoin_eau?: string + espacement_cm?: number + plantation_mois?: string + recolte_mois?: string + notes?: string +} + +export const varietiesApi = { + list: () => client.get('/api/varieties').then(r => r.data), + get: (id: number) => client.get(`/api/varieties/${id}`).then(r => r.data), + create: (v: Partial) => client.post('/api/varieties', v).then(r => r.data), + update: (id: number, v: Partial) => client.put(`/api/varieties/${id}`, v).then(r => r.data), + delete: (id: number) => client.delete(`/api/varieties/${id}`), +} diff --git a/frontend/src/stores/gardens.ts b/frontend/src/stores/gardens.ts new file mode 100644 index 0000000..baa6f81 --- /dev/null +++ b/frontend/src/stores/gardens.ts @@ -0,0 +1,27 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { gardensApi, type Garden } from '@/api/gardens' + +export const useGardensStore = defineStore('gardens', () => { + const gardens = ref([]) + const loading = ref(false) + + async function fetchAll() { + loading.value = true + gardens.value = await gardensApi.list() + loading.value = false + } + + async function create(g: Partial) { + const created = await gardensApi.create(g) + gardens.value.push(created) + return created + } + + async function remove(id: number) { + await gardensApi.delete(id) + gardens.value = gardens.value.filter(g => g.id !== id) + } + + return { gardens, loading, fetchAll, create, remove } +}) diff --git a/frontend/src/stores/plantings.ts b/frontend/src/stores/plantings.ts new file mode 100644 index 0000000..c082e94 --- /dev/null +++ b/frontend/src/stores/plantings.ts @@ -0,0 +1,27 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { plantingsApi, type Planting } from '@/api/plantings' + +export const usePlantingsStore = defineStore('plantings', () => { + const plantings = ref([]) + const loading = ref(false) + + async function fetchAll() { + loading.value = true + plantings.value = await plantingsApi.list() + loading.value = false + } + + async function create(p: Partial) { + const created = await plantingsApi.create(p) + plantings.value.push(created) + return created + } + + async function remove(id: number) { + await plantingsApi.delete(id) + plantings.value = plantings.value.filter(p => p.id !== id) + } + + return { plantings, loading, fetchAll, create, remove } +}) diff --git a/frontend/src/stores/tasks.ts b/frontend/src/stores/tasks.ts new file mode 100644 index 0000000..019b6ae --- /dev/null +++ b/frontend/src/stores/tasks.ts @@ -0,0 +1,34 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { tasksApi, type Task } from '@/api/tasks' + +export const useTasksStore = defineStore('tasks', () => { + const tasks = ref([]) + const loading = ref(false) + + async function fetchAll(params?: { statut?: string; garden_id?: number }) { + loading.value = true + tasks.value = await tasksApi.list(params) + loading.value = false + } + + async function create(t: Partial) { + const created = await tasksApi.create(t) + tasks.value.push(created) + return created + } + + async function updateStatut(id: number, statut: string) { + const t = tasks.value.find(t => t.id === id) + if (!t) return + const updated = await tasksApi.update(id, { ...t, statut }) + Object.assign(t, updated) + } + + async function remove(id: number) { + await tasksApi.delete(id) + tasks.value = tasks.value.filter(t => t.id !== id) + } + + return { tasks, loading, fetchAll, create, updateStatut, remove } +}) diff --git a/frontend/src/stores/varieties.ts b/frontend/src/stores/varieties.ts new file mode 100644 index 0000000..b68383a --- /dev/null +++ b/frontend/src/stores/varieties.ts @@ -0,0 +1,27 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { varietiesApi, type PlantVariety } from '@/api/varieties' + +export const useVarietiesStore = defineStore('varieties', () => { + const varieties = ref([]) + const loading = ref(false) + + async function fetchAll() { + loading.value = true + varieties.value = await varietiesApi.list() + loading.value = false + } + + async function create(v: Partial) { + const created = await varietiesApi.create(v) + varieties.value.push(created) + return created + } + + async function remove(id: number) { + await varietiesApi.delete(id) + varieties.value = varieties.value.filter(v => v.id !== id) + } + + return { varieties, loading, fetchAll, create, remove } +}) diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 479eb29..e8332b2 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -5,7 +5,8 @@ "moduleResolution": "bundler", "strict": true, "jsx": "preserve", - "lib": ["ES2020", "DOM"], + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "types": ["vite/client"], "skipLibCheck": true, "paths": { "@/*": ["./src/*"] } },