Projet Niv. 1 — Todo
Le brief : la liste de tâches — LE classique, fait proprement : SQLite, swipe, sections « aujourd’hui / plus tard », échéances avec rappels. Volontairement sans surprise : c’est la solidité qui est notée.
Ce que vous allez pratiquer
Le CRUD SQLite complet avec migrations (P8), FlatList et ses états (ch. 3.4), swipe-to-delete + annulation (ch. 10.4), TextInput/clavier (ch. 3.5), les notifications d’échéance (ch. 9.2). Chapitres liés : P8, 3.4, 3.5, 10.4, 9.2.
Les features
- CRUD : ajouter (champ en haut, retour clavier = valider), cocher/décocher, éditer (tap), supprimer (swipe + toast Annuler).
- Sections : En retard / Aujourd’hui / À venir / Un jour (tri par échéance).
- Échéance optionnelle avec rappel notification à l’heure dite.
- Le compteur : « 3 restantes aujourd’hui » — l’agrégat SQL en header.
- État vide soigné (la première impression).
L’architecture recommandée
- Le schéma (v1 — via le moteur de migrations du ch. 8.2, recopié tel quel) :
CREATE TABLE tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
done INTEGER NOT NULL DEFAULT 0,
due_at INTEGER, -- nullable : « un jour »
notification_id TEXT, -- pour annuler le rappel si la tâche bouge
created_at INTEGER NOT NULL
);
CREATE INDEX idx_tasks_due ON tasks(done, due_at);- La colonne
notification_idest LA leçon du projet : une tâche avec rappel stocke l’identifiant de SA notification planifiée — cocher/supprimer/reporter la tâche annule et replanifie. La cohérence données ↔ notifications est un vrai sujet d’app réelle. - Une seule requête pour les sections :
SELECT …, CASE WHEN … END AS section(ou le tri par due_at et le groupement en JS via SectionList — les deux se défendent : choisissez et justifiez dans le README). - TanStack Query sur les hooks de données + invalidation après mutations (ch. 8.3) — le pattern se recopie.
Les jalons
- Schéma + migrations + lib/db/tasks.ts (insert, toggle, update, delete, listBySections).
- La liste : sections, ajout au clavier, cocher (avec le barré animé — LayoutAnimation).
- Swipe-to-delete + toast d’annulation (suppression optimiste, écriture différée).
- Échéances : le picker (badges Aujourd’hui/Demain/Date), le rappel notification, et la cohérence annulation/replanification.
- Header d’agrégats + état vide + APK.
Critères de réussite
- 200 tâches insérées (script de seed) : la liste reste fluide (items mémoïsés)
- Cocher une tâche à rappel futur ANNULE sa notification (vérifiable : getAllScheduledNotificationsAsync)
- Le swipe supprimé + Annuler dans les 5 s : la tâche revient, la base n’a jamais bougé
- Kill + relance : tout est là (SQLite), les sections justes (dates recalculées)
- Le clavier ne masque jamais le champ d’ajout, le premier tap sur une tâche passe (keyboardShouldPersistTaps)
- APK installé, utilisé une semaine RÉELLE (le seul vrai test d’un todo)
Pièges connus
- « Aujourd’hui » se calcule en heure locale (le strftime localtime du ch. 8.3 — ou le calcul JS du début de journée locale) : une tâche de 23 h 50 n’est pas « en retard » à 00 h 01 UTC.
- Ne stockez pas la SECTION en base (elle dérive de due_at et de MAINTENANT — dériver, jamais stocker, ch. 6.1).
- L’édition inline (tap → TextInput à la place du Text) est plus délicate qu’un écran d’édition — commencez par l’écran, l’inline en bonus.
💡 L’upgrade : les sous-tâches (une colonne parent_id — et la récursivité SQL
WITH RECURSIVEen cadeau d’apprentissage), ou le widget « ajouter depuis le partage » (l’app reçoit du texte partagé — expo-share-intent, module natif : votre premier hors-SDK).