From 580aab822addd58e30c9ce1fa55f4709c20019ac Mon Sep 17 00:00:00 2001 From: Gilles Soulier Date: Sun, 24 May 2026 12:10:31 +0200 Subject: [PATCH] =?UTF-8?q?feat(todos):=20composant=20TodoForm=20(rapide?= =?UTF-8?q?=20mobile=20/=20=C3=A9tendu=20laptop)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/todos/TodoForm.tsx | 147 +++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 frontend/src/components/todos/TodoForm.tsx diff --git a/frontend/src/components/todos/TodoForm.tsx b/frontend/src/components/todos/TodoForm.tsx new file mode 100644 index 0000000..513b37b --- /dev/null +++ b/frontend/src/components/todos/TodoForm.tsx @@ -0,0 +1,147 @@ +import { useState } from 'react' +import type { TodoCreate } from '../../api/todos' + +const DOMAINS = [ + 'informatique', 'diy', 'electronique', 'domotique', + 'bricolage', 'jardin', 'cuisine', 'voyage', 'animaux', +] + +interface TodoFormProps { + onSubmit: (data: TodoCreate) => Promise + onCancel: () => void + extended?: boolean // true = tous les champs (vue laptop) +} + +const inputStyle: React.CSSProperties = { + width: '100%', + background: 'var(--bg-4)', + border: '1px solid var(--bg-5)', + borderRadius: 8, + padding: '10px 12px', + color: 'var(--ink-1)', + fontFamily: 'var(--font-ui)', + fontSize: 14, + boxSizing: 'border-box', +} + +export default function TodoForm({ onSubmit, onCancel, extended = false }: TodoFormProps) { + const [title, setTitle] = useState('') + const [domain, setDomain] = useState('') + const [priority, setPriority] = useState('medium') + const [dueDate, setDueDate] = useState('') + const [body, setBody] = useState('') + const [url, setUrl] = useState('') + const [tags, setTags] = useState('') + const [loading, setLoading] = useState(false) + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault() + if (!title.trim()) return + setLoading(true) + try { + await onSubmit({ + title: title.trim(), + domain: domain || undefined, + priority, + due_date: dueDate ? new Date(dueDate).toISOString() : undefined, + body: body.trim() || undefined, + url: url.trim() || undefined, + tags: tags ? tags.split(',').map(t => t.trim()).filter(Boolean) : [], + }) + } finally { + setLoading(false) + } + } + + return ( +
+ setTitle(e.target.value)} + autoFocus + required + /> + +
+ + +
+ + setDueDate(e.target.value)} + placeholder="Date objectif" + /> + + {extended && ( + <> +