diff --git a/frontend/src/api/todos.ts b/frontend/src/api/todos.ts index 2f9c690..e145bd0 100644 --- a/frontend/src/api/todos.ts +++ b/frontend/src/api/todos.ts @@ -23,8 +23,8 @@ export interface TodoCreate { domain?: string category?: string tags?: string[] - status?: string - priority?: string + status?: 'pending' | 'done' | 'cancelled' + priority?: 'low' | 'medium' | 'high' due_date?: string } @@ -35,8 +35,8 @@ export interface TodoUpdate { domain?: string category?: string tags?: string[] - status?: string - priority?: string + status?: 'pending' | 'done' | 'cancelled' + priority?: 'low' | 'medium' | 'high' due_date?: string } diff --git a/frontend/src/components/todos/SwipeableRow.tsx b/frontend/src/components/todos/SwipeableRow.tsx index 2a34ee5..e387293 100644 --- a/frontend/src/components/todos/SwipeableRow.tsx +++ b/frontend/src/components/todos/SwipeableRow.tsx @@ -10,17 +10,16 @@ const THRESHOLD = 80 // pixels pour déclencher une action export default function SwipeableRow({ children, rightContent, onSwipeRight }: SwipeableRowProps) { const [offsetX, setOffsetX] = useState(0) + const [isDragging, setIsDragging] = useState(false) const startX = useRef(null) - const dragging = useRef(false) function onTouchStart(e: React.TouchEvent) { startX.current = e.touches[0].clientX - dragging.current = false + setIsDragging(true) } function onTouchMove(e: React.TouchEvent) { if (startX.current === null) return - dragging.current = true const dx = e.touches[0].clientX - startX.current // Clamp : +120px à droite, -160px à gauche (largeur des boutons) setOffsetX(Math.max(Math.min(dx, 120), -160)) @@ -31,8 +30,8 @@ export default function SwipeableRow({ children, rightContent, onSwipeRight }: S onSwipeRight() } setOffsetX(0) + setIsDragging(false) startX.current = null - dragging.current = false } const revealActions = offsetX < -(THRESHOLD / 2) @@ -64,7 +63,7 @@ export default function SwipeableRow({ children, rightContent, onSwipeRight }: S onTouchEnd={onTouchEnd} style={{ transform: `translateX(${offsetX}px)`, - transition: dragging.current ? 'none' : 'transform 0.2s ease', + transition: isDragging ? 'none' : 'transform 0.2s ease', background: offsetX > THRESHOLD / 2 ? 'var(--ok)' : 'var(--bg-3)', position: 'relative', zIndex: 1, diff --git a/frontend/src/pages/TodosPage.tsx b/frontend/src/pages/TodosPage.tsx index f4a5d84..c0c9edf 100644 --- a/frontend/src/pages/TodosPage.tsx +++ b/frontend/src/pages/TodosPage.tsx @@ -29,13 +29,17 @@ const selectStyle: React.CSSProperties = { export default function TodosPage() { const [todos, setTodos] = useState([]) const [loading, setLoading] = useState(true) + const [error, setError] = useState(null) const [showForm, setShowForm] = useState(false) const [filters, setFilters] = useState({ status: 'pending' }) const load = useCallback(async () => { setLoading(true) + setError(null) try { setTodos(await fetchTodos(filters)) + } catch { + setError('Erreur lors du chargement des tâches') } finally { setLoading(false) } @@ -44,24 +48,40 @@ export default function TodosPage() { useEffect(() => { void load() }, [load]) async function handleCreate(data: TodoCreate) { - await createTodo(data) - setShowForm(false) - void load() + try { + await createTodo(data) + setShowForm(false) + void load() + } catch { + setError('Erreur lors de la création') + } } async function handleDone(id: string) { - await updateTodo(id, { status: 'done' }) - void load() + try { + await updateTodo(id, { status: 'done' }) + void load() + } catch { + setError('Erreur lors de la mise à jour') + } } async function handleDelete(id: string) { - await deleteTodo(id) - void load() + try { + await deleteTodo(id) + void load() + } catch { + setError('Erreur lors de la suppression') + } } async function handlePostpone(id: string, days: 1 | 7) { - await postponeTodo(id, days) - void load() + try { + await postponeTodo(id, days) + void load() + } catch { + setError('Erreur lors du report') + } } // Grouper par domaine pour la vue mobile @@ -110,6 +130,12 @@ export default function TodosPage() { + {error && ( +

+ {error} +

+ )} + {/* Formulaire de création */} {showForm && (