Skip to content

Latest commit

 

History

History
293 lines (217 loc) · 15.5 KB

File metadata and controls

293 lines (217 loc) · 15.5 KB

🗺️ Roadmap AquaTrack

Améliorations et enrichissements proposés pour AquaTrack, en conservant la légèreté et l’absence de backend (données 100 % locales, app statique).


Principes directeurs

  • No backend : données uniquement dans IndexedDB
  • Légèreté : pas de nouvelles dépendances lourdes, privilégier les APIs natives
  • App statique : déploiement inchangé (FTP, Netlify, Vercel, etc.)
  • Expérience utilisateur : gains concrets pour l’aquariophile au quotidien

Phase 1 – Quick wins (effort faible)

1.1 Copie du dernier relevé

Effort : ~30 min
Remplir automatiquement le formulaire « Nouveau relevé » avec les valeurs du dernier relevé. L’utilisateur n’a plus qu’à modifier les paramètres qui ont changé. Gain de temps important lors des relevés réguliers.

1.2 Filtrage par période dans l’historique

Effort : ~1 h
Filtres rapides : 7 jours, 30 jours, 90 jours, tout. Les graphiques et le tableau s’adaptent. Utile pour comparer des tendances sur différentes échelles.

1.3 Indicateurs de tendance

Effort : ~45 min

Objectif : Lecture immédiate de l’évolution de chaque paramètre sans ouvrir l’historique.

Comportement :

  • Comparer la valeur actuelle (dernier relevé) avec le relevé précédent.
  • Afficher un symbole à côté de chaque valeur : ↑ (hausse), ↓ (baisse), → (stable).
  • Seuil de stabilité : considérer « stable » si la variation absolue < 0.1 (ou 5 % pour les grandes valeurs). À définir par paramètre si besoin (ex. NO₂ sensible à 0.05, GH moins).
  • Couleur du symbole :
    • Vert : valeur actuelle dans la plage [minSafe, maxSafe].
    • Rouge : valeur actuelle hors plage (danger).
    • Orange/ambre (optionnel) : valeur dans les normes mais tendance inquiétante (ex. NO₂ qui monte vers 0.5).

Implémentation :

  • Dans le dashboard, pour chaque carte paramètre : const prev = readings[1]?.[param.key].
  • Helper getTrend(current, prev, tolerance)'up' | 'down' | 'stable'.
  • Icônes : TrendingUp, TrendingDown, Minus (lucide-react) ou caractères Unicode (↑ ↓ →).
  • Tooltip optionnel : « 0.3 → 0.4 (+0.1) » pour afficher la variation exacte.

Cas limites :

  • Un seul relevé : pas d’indicateur (ou afficher « — »).
  • Valeurs identiques : → (stable).

1.4 Zone de sécurité sur les graphiques

Effort : ~1 h
Afficher une bande (ReferenceArea de Recharts) entre minSafe et maxSafe sur les courbes. Les dépassements sont visuels sans calcul mental.

1.5 Export / import JSON

Effort : ~1 h

  • Export : bouton pour télécharger un fichier JSON de tous les relevés.
  • Import : bouton pour recharger un fichier JSON (fusion ou remplacement).
  • Permet sauvegarde, restauration, changement de navigateur ou d’appareil, sans backend.

Phase 2 – Expérience utilisateur

2.1 PWA (Progressive Web App)

Effort : ~2 h

  • manifest.json + icônes pour installation sur mobile/desktop.
  • Service Worker pour fonctionnement hors ligne (lecture + création de relevés).
  • Les données IndexedDB restent locales, aucune synchro serveur.
  • Légèreté : pas de librairie, juste config Vite/PWA (optionnel, plugin existant très léger).

2.2 Mode sombre

Effort : ~1 h 30

Objectif : Confort visuel en conditions de faible luminosité (pièce sombre, aquarium éteint la nuit).

Approche technique :

  • Tailwind : le projet utilise le CDN Tailwind. Configurer darkMode: 'class' dans tailwind.config.js (si fichier dédié) ou via la directive dark dans le <html>.
  • Variable de préférence : localStorage.setItem('theme', 'dark'|'light'|'system').
  • Détection système : window.matchMedia('(prefers-color-scheme: dark)') pour le mode « système ».
  • Appliquer document.documentElement.classList.add/remove('dark') au chargement et à chaque changement.

Mapping des couleurs :

  • Fond : bg-slate-50dark:bg-slate-900.
  • Cartes : bg-whitedark:bg-slate-800.
  • Texte : text-slate-900dark:text-slate-100, text-slate-500dark:text-slate-400.
  • Bordures : border-slate-200dark:border-slate-700.
  • Accent cyan : garder ou légèrement ajuster (dark:from-cyan-500 dark:to-blue-500) pour rester lisible.

UI du sélecteur :

  • Bouton ou menu dans la navbar : icône soleil/lune, ou liste « Clair / Sombre / Système ».
  • Toggle simple si on ne propose que clair/sombre.

Aucune dépendance : tout en CSS + localStorage + matchMedia.

2.3 Rappels de maintenance

Effort : ~2 h

Objectif : Rappeler à l’utilisateur de faire un relevé sans oublier, sans backend ni push.

Paramètres configurables (stockés en localStorage ou dans un store IndexedDB settings) :

  • Fréquence : 1x/semaine (7 j), 2x/semaine (3–4 j), 1x/2 semaines (14 j), personnalisé (nombre de jours).
  • Heure de rappel (optionnel) : ex. 18h pour rappel en fin de journée.

Logique :

  • Au chargement de l’app : lastReadingDate = readings[0]?.date.
  • daysSinceLastReading = (now - lastReadingDate) / (24*60*60*1000).
  • Si daysSinceLastReading >= frequencyDays → demander l’autorisation de notification (si pas encore accordée), puis afficher une notification.

Notification API :

  • Notification.requestPermission() : demander au premier usage ou via un bouton « Activer les rappels ».
  • new Notification('AquaTrack', { body: 'Pensez à faire votre relevé d\'eau cette semaine.' }) lorsque la condition est remplie.
  • Vérifier la condition au chargement ET via un setInterval (ex. toutes les heures) ou lors du retour en premier plan (document.visibilitychange) pour couvrir les sessions longues.

Éviter le spam :

  • Ne pas notifier plus d’une fois par jour.
  • Stocker lastNotificationDate en localStorage pour ne pas répéter la même notification.

Fallback :

  • Si les notifications sont refusées ou indisponibles : afficher un bandeau dans l’app « Prochain relevé recommandé dans X jours » ou « Relevé en retard de X jours » sur le dashboard.

2.4 Plusieurs aquariums

Effort : ~3 h

  • Sélecteur d’aquarium (ex. « Aquarium principal », « Nano cube »).

  • Stockage dans IndexedDB avec une clé aquariumId par relevé.

  • Pas de backend : un store par aquarium ou une table avec filtre.

  • Légèreté : juste une table/objet de plus, pas d’API.

  • Articulation : implémenté avec le support poissons et espèces (2.6) : même entité aquarium et même aquariumId sur les relevés.

2.6 Support des poissons et espèces aquatiques

Effort : ~8–10 h

Objectif : Base de données d'espèces, gestion d'aquariums (nom, volume) liée aux paramètres, peuplement en poissons et vérification de la compatibilité des paramètres (température, pH, GH) avec les exigences de chaque espèce.

Base de données d'espèces :

  • Plus de 200 poissons d'aquarium d'eau douce avec fiche technique résumée : taille (min/max cm), volume min (L), difficulté d'élevage, robustesse, comportement, température (°C), pH, GH (°dGH), population min, etc.
  • Données en lecture seule : fichier JSON statique livré avec l'app (public/data/species.json), pas d'IndexedDB pour le catalogue.
  • Source : données dérivées de Fishipedia (script d'extraction one-shot ou JSON pré-rempli). Usage strictement local, pas d'API temps réel. Citer la source dans l'app (« Données issues de Fishipedia »).

Entité aquarium (en lien avec 2.4) :

  • Création d'un aquarium : nom, volume (L). Stockage IndexedDB (object store aquariums).
  • Relevés rattachés à un aquarium via aquariumId. Température ajoutée au relevé (optionnel) pour la comparaison avec les plages des espèces.

Peuplement et compatibilité :

  • Ajout de poissons à un aquarium : choix d'une espèce (catalogue) + nombre d'individus. Stockage dans un store aquarium_stock (aquariumId, speciesId, count).
  • Vérification de compatibilité : pour chaque espèce présente dans l'aquarium, comparer le dernier relevé (température, pH, GH) aux plages optimales de l'espèce. Afficher un statut par paramètre ou par espèce : Optimal (dans la plage), Attention (proche des bornes), Inadapté (hors plage). Gérer l'absence de valeur (ex. température non renseignée) par « Non renseigné ».

UI :

  • Navigation : entrées « Aquariums » et « Espèces » (catalogue des 100+ poissons, recherche/filtre, fiche résumée au clic).
  • Aquariums : liste, création, détail (dernier relevé, liste des poissons, bouton « Ajouter des poissons »), bloc « Compatibilité » avec indicateurs Optimal / Attention / Inadapté.
  • Formulaire de relevé : sélecteur d'aquarium (si plusieurs), champ température.

2.5 Jalons / événements

Effort : ~2 h

Objectif : Corréler les actions de maintenance avec l'évolution des paramètres (ex. pic de NO₂ après introduction de poissons).

Modèle de données (IndexedDB, nouvel object store events) :

interface AquaEvent {
  id: string;
  date: string;        // ISO string, comme WaterReading
  type: EventType;     // 'water_change' | 'treatment' | 'new_fish' | 'filter_clean' | 'fertilizer' | 'other'
  notes?: string;
  aquariumId?: string; // si multi-aquariums (2.4)
}
  • Types prédéfinis avec icônes : changement d'eau (Droplets), traitement (Pill), nouveaux poissons (Fish), nettoyage filtre (Filter), engrais (Leaf), autre (Circle).

UI :

  • Ajout : bouton « Ajouter un événement » (formulaire léger : date, type, notes).
  • Historique : liste ou timeline sous le tableau des relevés, ou section dédiée.
  • Graphiques : ReferenceLine Recharts avec x = event.date pour chaque événement. Ou petites marqueurs/lignes verticales cliquables avec tooltip (type + notes).

Stockage :

  • Migration IndexedDB : DB_VERSION = 2, créer le store events dans l'upgrade.
  • CRUD : getEvents(), createEvent(), deleteEvent().

Affichage sur le graphique :

  • Trier les événements par date. Pour chaque événement dans la plage affichée, ajouter une ReferenceLine avec x={formattedDate} et label={{ value: type, position: 'top' }}.
  • Couleur différente par type (optionnel) pour distinguer visuellement.

Phase 3 – Valeur ajoutée

3.1 Conseils contextuels

Effort : ~2 h

Objectif : Guider l'utilisateur avec des messages courts et pertinents selon l'état actuel des paramètres.

Structure des règles (données en dur dans le code, pas d'API) :

interface AdviceRule {
  param: keyof WaterReading;
  condition: (value: number, min: number, max: number) => boolean;
  message: string;
  severity: 'info' | 'warning' | 'danger';
}
  • Exemples : NO₂ > 0 → danger « Cycle incomplet ou déséquilibré. Évitez d'ajouter des poissons. » ; CO₂ < 15 → info « Les plantes peuvent manquer de CO₂. » ; NO₃ > 40 → warning « Nitrates élevés. Envisagez un changement d'eau. » ; pH < 6 ou > 8 → warning selon le sens.

Où afficher :

  • Dashboard : bloc « Conseils » sous les cartes paramètres, listant les messages actifs (ceux dont la condition est vraie).
  • Formulaire de relevé : messages en temps réel sous chaque champ si valeur hors plage (déjà partiellement présent via « Optimal / Attention »).

Implémentation :

  • Boucler sur les règles, évaluer condition(latestReading[param], minSafe, maxSafe), collecter les messages.
  • Trier par severity (danger > warning > info) et afficher.
  • Éviter les doublons (une règle par paramètre concerné).

3.2 Suggestion de fréquence de changement d'eau

Effort : ~1 h 30

Objectif : Proposer une date pour le prochain relevé ou un changement d'eau, de façon indicative.

Critères (algorithme heuristique simple) :

  • NO₃ élevé (> 40 mg/L) : « Changement d'eau recommandé » + « Relevé conseillé dans 3 jours ».
  • NO₃ modéré (20–40) : « Relevé dans 5–7 jours ».
  • NO₃ bas (< 20) : « Relevé dans 7–10 jours » (ou selon la fréquence configurée en 2.3).
  • Paramètres hors norme (NO₂ > 0, Cl₂ > 0, etc.) : priorité « Relevé et action rapide recommandés ».
  • GH/KH : si très bas ou très haut, mention optionnelle « Vérifiez la dureté lors du prochain changement ».

Sortie :

  • Message texte : ex. « Prochain relevé suggéré : dans 5 jours » ou « Changement d'eau recommandé – NO₃ élevé ».
  • Date calculée : nextDate = new Date(lastReading.date); nextDate.setDate(nextDate.getDate() + suggestedDays).
  • Afficher dans un encart sur le dashboard, près du bloc « Dernier relevé » ou dans la zone conseils (3.1).

Indicatif : préciser « Suggestion indicative, adaptez selon votre bac et vos habitudes. »

3.3 Impression / export PDF

Effort : ~2 h
Bouton « Imprimer le rapport » : vue optimisée pour impression (CSS @media print). Optionnel : export PDF via window.print() + « Enregistrer en PDF » ou lib légère type jsPDF uniquement si nécessaire. Priorité à l’impression native pour rester léger.

3.4 Paramètres optionnels / personnalisables

Effort : ~2 h 30
Permettre de masquer certains paramètres (ex. pas de CO₂ si pas de système CO₂) ou d’ajouter des paramètres personnalisés (conductivité, température). Configuration stockée en localStorage.


Phase 4 – Finesse (optionnel)

4.1 Accessibilité

  • Contraste élevé optionnel.
  • Navigation au clavier améliorée.
  • Labels ARIA et structure sémantique.

4.2 Pagination / virtualisation

Si l’historique dépasse 500+ relevés : pagination ou virtualisation du tableau pour garder l’app fluide. Probablement rare en usage normal.

4.3 Statistiques résumées

Moyennes, min, max sur une période choisie. Utile pour un bilan mensuel ou trimestriel.


Dépendances à éviter

Pour rester léger et sans backend :

  • ❌ Pas de Firebase, Supabase, ou autre BaaS.
  • ❌ Pas de librairie d’état globale (Redux, Zustand) si l’état actuel suffit.
  • ❌ Pas d’analytics ou de tracking externe par défaut.
  • ✅ Préférer : APIs natives (IndexedDB, Notifications, Storage), CSS, petites fonctions utilitaires maison.

Priorisation suggérée

Priorité Élément Impact Effort
1 Copie dernier relevé (1.1) ★★★ Faible
2 Export / import JSON (1.5) ★★★ Faible
3 Filtrage par période (1.2) ★★☆ Faible
4 Zone sécurité graphiques (1.4) ★★☆ Faible
5 PWA (2.1) ★★★ Moyen
6 Indicateurs tendance (1.3) ★★☆ Faible
7 Mode sombre (2.2) ★★☆ Faible
8 Plusieurs aquariums (2.4) ★★★ Moyen
9 Conseils contextuels (3.1) ★★☆ Faible
10 Jalons / événements (2.5) ★★☆ Moyen

Notes techniques

  • IndexedDB : possible d’ajouter des object stores (events, aquariums, settings) sans migration complexe en gérant les versions de DB.
  • Recharts : déjà présent ; ReferenceArea, ReferenceLine permettent les zones de sécurité.
  • Service Worker : optionnel ; Workbox ou plugin Vite PWA restent légers si tu veux une vraie PWA.
  • Build : aucun impact sur le déploiement statique ; dist/ reste une collection de fichiers HTML/CSS/JS.

Dernière mise à jour : janvier 2025