avant codex
This commit is contained in:
@@ -1,42 +1,11 @@
|
||||
<template>
|
||||
<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>
|
||||
<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="openCreate">+ 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>
|
||||
@@ -47,26 +16,80 @@
|
||||
'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">
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="text-text text-sm">{{ t.titre }}</div>
|
||||
<div v-if="t.echeance" class="text-text-muted text-xs">📅 {{ fmtDate(t.echeance) }}</div>
|
||||
</div>
|
||||
<div class="flex gap-1 items-center shrink-0">
|
||||
<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>
|
||||
<button @click="startEdit(t)" class="text-xs text-yellow hover:underline ml-2">Édit.</button>
|
||||
<button class="text-xs text-text-muted hover:text-red ml-1" @click="store.remove(t.id!)">✕</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal création / édition -->
|
||||
<div v-if="showForm" class="fixed inset-0 bg-black/60 z-50 flex items-center justify-center p-4" @click.self="closeForm">
|
||||
<div class="bg-bg-hard rounded-xl p-6 w-full max-w-md border border-bg-soft">
|
||||
<h2 class="text-text font-bold text-lg mb-4">{{ editId ? 'Modifier la tâche' : 'Nouvelle tâche' }}</h2>
|
||||
<form @submit.prevent="submit" 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>
|
||||
<label class="text-text-muted text-xs block mb-1">Description</label>
|
||||
<textarea v-model="form.description" rows="2"
|
||||
class="w-full bg-bg border border-bg-hard rounded px-3 py-2 text-text text-sm focus:border-green outline-none resize-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">Statut</label>
|
||||
<select v-model="form.statut" class="w-full bg-bg border border-bg-hard rounded px-3 py-2 text-text text-sm">
|
||||
<option value="a_faire">À faire</option>
|
||||
<option value="en_cours">En cours</option>
|
||||
<option value="fait">Terminé</option>
|
||||
</select>
|
||||
</div>
|
||||
</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 class="flex gap-2 mt-2">
|
||||
<button type="submit" class="bg-green text-bg px-4 py-2 rounded text-sm font-semibold">
|
||||
{{ editId ? 'Enregistrer' : 'Créer' }}
|
||||
</button>
|
||||
<button type="button" class="text-text-muted text-sm px-4 py-2 hover:text-text" @click="closeForm">Annuler</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { useTasksStore } from '@/stores/tasks'
|
||||
import type { Task } from '@/api/tasks'
|
||||
|
||||
const store = useTasksStore()
|
||||
const showForm = ref(false)
|
||||
const form = reactive({ titre: '', priorite: 'normale', statut: 'a_faire', echeance: '' })
|
||||
const editId = ref<number | null>(null)
|
||||
const form = reactive({ titre: '', description: '', priorite: 'normale', statut: 'a_faire', echeance: '' })
|
||||
|
||||
const groupes: [string, string][] = [
|
||||
['a_faire', 'À faire'],
|
||||
@@ -76,11 +99,36 @@ const groupes: [string, string][] = [
|
||||
|
||||
const byStatut = (s: string) => store.tasks.filter(t => t.statut === s)
|
||||
|
||||
function fmtDate(s: string) {
|
||||
return new Date(s + 'T12:00:00').toLocaleDateString('fr-FR', { day: 'numeric', month: 'short' })
|
||||
}
|
||||
|
||||
function openCreate() {
|
||||
editId.value = null
|
||||
Object.assign(form, { titre: '', description: '', priorite: 'normale', statut: 'a_faire', echeance: '' })
|
||||
showForm.value = true
|
||||
}
|
||||
|
||||
function startEdit(t: Task) {
|
||||
editId.value = t.id!
|
||||
Object.assign(form, {
|
||||
titre: t.titre, description: (t as any).description || '',
|
||||
priorite: t.priorite, statut: t.statut,
|
||||
echeance: t.echeance ? t.echeance.slice(0, 10) : '',
|
||||
})
|
||||
showForm.value = true
|
||||
}
|
||||
|
||||
function closeForm() { showForm.value = false; editId.value = null }
|
||||
|
||||
onMounted(() => store.fetchAll())
|
||||
|
||||
async function submit() {
|
||||
await store.create({ ...form })
|
||||
showForm.value = false
|
||||
Object.assign(form, { titre: '', priorite: 'normale', statut: 'a_faire', echeance: '' })
|
||||
if (editId.value) {
|
||||
await store.update(editId.value, { ...form })
|
||||
} else {
|
||||
await store.create({ ...form })
|
||||
}
|
||||
closeForm()
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user