feat(frontend): vues MVP — dashboard, jardins, grille, variétés, tâches, plantations

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-22 04:18:11 +01:00
parent 3c5f0d571f
commit 911395accc
9 changed files with 398 additions and 18 deletions

View File

@@ -1,5 +1,86 @@
<template>
<div class="p-4">
<h1 class="text-2xl font-bold text-green">Tâches</h1>
<div class="p-4 max-w-2xl mx-auto">
<div class="flex items-center justify-between mb-6">
<h1 class="text-2xl font-bold text-green">Tâches</h1>
<button
class="bg-green text-bg px-4 py-2 rounded-lg text-sm font-semibold hover:opacity-90"
@click="showForm = !showForm"
>+ Nouvelle</button>
</div>
<form v-if="showForm" class="bg-bg-soft rounded-lg p-4 mb-6 border border-green/30" @submit.prevent="submit">
<div class="grid gap-3">
<div>
<label class="text-text-muted text-xs block mb-1">Titre *</label>
<input v-model="form.titre" required
class="w-full bg-bg border border-bg-hard rounded px-3 py-2 text-text text-sm focus:border-green outline-none" />
</div>
<div class="grid grid-cols-2 gap-3">
<div>
<label class="text-text-muted text-xs block mb-1">Priorité</label>
<select v-model="form.priorite" class="w-full bg-bg border border-bg-hard rounded px-3 py-2 text-text text-sm">
<option value="basse">Basse</option>
<option value="normale">Normale</option>
<option value="haute">Haute</option>
</select>
</div>
<div>
<label class="text-text-muted text-xs block mb-1">Échéance</label>
<input v-model="form.echeance" type="date"
class="w-full bg-bg border border-bg-hard rounded px-3 py-2 text-text text-sm focus:border-green outline-none" />
</div>
</div>
</div>
<div class="flex gap-2 mt-4">
<button type="submit" class="bg-green text-bg px-4 py-2 rounded text-sm font-semibold">Créer</button>
<button type="button" class="text-text-muted text-sm px-4 py-2 hover:text-text" @click="showForm = false">Annuler</button>
</div>
</form>
<div v-for="[groupe, label] in groupes" :key="groupe" class="mb-6">
<h2 class="text-text-muted text-xs uppercase tracking-widest mb-2">{{ label }}</h2>
<div v-if="!byStatut(groupe).length" class="text-text-muted text-xs pl-2 mb-2"></div>
<div v-for="t in byStatut(groupe)" :key="t.id"
class="bg-bg-soft rounded-lg p-3 mb-2 flex items-center gap-3 border border-bg-hard">
<span :class="{
'text-red': t.priorite === 'haute',
'text-yellow': t.priorite === 'normale',
'text-text-muted': t.priorite === 'basse'
}"></span>
<span class="text-text text-sm flex-1">{{ t.titre }}</span>
<div class="flex gap-1 items-center">
<button v-if="t.statut === 'a_faire'" class="text-xs text-blue hover:underline"
@click="store.updateStatut(t.id!, 'en_cours')"> En cours</button>
<button v-if="t.statut === 'en_cours'" class="text-xs text-green hover:underline"
@click="store.updateStatut(t.id!, 'fait')"> Fait</button>
<button class="text-xs text-text-muted hover:text-red ml-2" @click="store.remove(t.id!)"></button>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue'
import { useTasksStore } from '@/stores/tasks'
const store = useTasksStore()
const showForm = ref(false)
const form = reactive({ titre: '', priorite: 'normale', statut: 'a_faire', echeance: '' })
const groupes: [string, string][] = [
['a_faire', 'À faire'],
['en_cours', 'En cours'],
['fait', 'Terminé'],
]
const byStatut = (s: string) => store.tasks.filter(t => t.statut === s)
onMounted(() => store.fetchAll())
async function submit() {
await store.create({ ...form })
showForm.value = false
Object.assign(form, { titre: '', priorite: 'normale', statut: 'a_faire', echeance: '' })
}
</script>