docs: update README, add DB schema (Mermaid) and roadmap
This commit is contained in:
@@ -0,0 +1,503 @@
|
||||
# 📊 HabitForge - Database Schema
|
||||
|
||||
> Diagrammes Mermaid du schéma de base de données
|
||||
|
||||
---
|
||||
|
||||
## Vue d'Ensemble (Core + Health Connect)
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
users ||--o{ challenges : "owns"
|
||||
users ||--o{ daily_health_metrics : "tracks"
|
||||
users ||--o{ daily_context : "logs"
|
||||
users ||--o{ workout_sessions : "records"
|
||||
users ||--o{ health_connect_sync_logs : "syncs"
|
||||
challenges ||--o{ trackings : "has"
|
||||
|
||||
users {
|
||||
int id PK
|
||||
string username UK
|
||||
string hashed_password
|
||||
}
|
||||
|
||||
challenges {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string name
|
||||
string period_type
|
||||
int daily_target
|
||||
date start_date
|
||||
date end_date
|
||||
date created_at
|
||||
int display_order
|
||||
string unit_type
|
||||
string rest_days
|
||||
string icon
|
||||
string image_url
|
||||
string description
|
||||
int frequency_count
|
||||
string selected_days
|
||||
}
|
||||
|
||||
tracking {
|
||||
int id PK
|
||||
int challenge_id FK
|
||||
date date
|
||||
int reps
|
||||
boolean completed
|
||||
text notes
|
||||
}
|
||||
|
||||
daily_health_metrics {
|
||||
int id PK
|
||||
int user_id FK
|
||||
date date
|
||||
int step_count
|
||||
float distance_meters
|
||||
float calories_burned
|
||||
int sleep_duration_minutes
|
||||
int deep_sleep_minutes
|
||||
int light_sleep_minutes
|
||||
int rem_sleep_minutes
|
||||
int awake_duration_minutes
|
||||
int avg_heart_rate
|
||||
int min_heart_rate
|
||||
int max_heart_rate
|
||||
float avg_spo2
|
||||
float pai_score
|
||||
float weight
|
||||
int resting_heart_rate
|
||||
float hrv
|
||||
string data_source
|
||||
}
|
||||
|
||||
daily_context {
|
||||
int id PK
|
||||
int user_id FK
|
||||
date date
|
||||
int mood_score
|
||||
string tags
|
||||
string notes
|
||||
}
|
||||
|
||||
workout_sessions {
|
||||
int id PK
|
||||
int user_id FK
|
||||
datetime start_time
|
||||
datetime end_time
|
||||
string activity_type
|
||||
int activity_type_id
|
||||
int duration_seconds
|
||||
float distance_meters
|
||||
float calories
|
||||
float avg_pace
|
||||
float max_pace
|
||||
float min_pace
|
||||
int avg_hr
|
||||
int max_hr
|
||||
int min_hr
|
||||
string notes
|
||||
string data_source
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Health Connect (Sync & Agrégé)
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
users ||--o{ health_connect_sync_logs : "syncs"
|
||||
users ||--o{ health_connect_daily_metrics : "aggregates"
|
||||
users ||--o{ health_connect_exercise_sessions : "exercises"
|
||||
health_connect_sync_logs ||--o{ health_connect_daily_metrics : "produced"
|
||||
health_connect_sync_logs ||--o{ health_connect_exercise_sessions : "produced"
|
||||
|
||||
health_connect_sync_logs {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string device_id
|
||||
datetime sync_timestamp
|
||||
int records_pushed
|
||||
string status
|
||||
text error_message
|
||||
}
|
||||
|
||||
health_connect_daily_metrics {
|
||||
int id PK
|
||||
int user_id FK
|
||||
date date
|
||||
string data_source
|
||||
string data_source_name
|
||||
int step_count
|
||||
float distance_meters
|
||||
float calories_burned
|
||||
float total_calories
|
||||
int sleep_duration_minutes
|
||||
int deep_sleep_minutes
|
||||
int light_sleep_minutes
|
||||
int rem_sleep_minutes
|
||||
int awake_duration_minutes
|
||||
int avg_heart_rate
|
||||
int min_heart_rate
|
||||
int max_heart_rate
|
||||
int resting_heart_rate
|
||||
float avg_spo2
|
||||
float min_spo2
|
||||
float max_spo2
|
||||
float weight
|
||||
datetime last_synced
|
||||
int sync_id FK
|
||||
}
|
||||
|
||||
health_connect_exercise_sessions {
|
||||
int id PK
|
||||
int user_id FK
|
||||
datetime start_time
|
||||
datetime end_time
|
||||
int exercise_type
|
||||
string exercise_type_name
|
||||
int duration_seconds
|
||||
float distance_meters
|
||||
float calories_burned
|
||||
int avg_heart_rate
|
||||
int max_heart_rate
|
||||
int min_heart_rate
|
||||
int steps
|
||||
float elevation_gained
|
||||
text notes
|
||||
datetime last_synced
|
||||
int sync_id FK
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Health Connect Raw Data (15 tables)
|
||||
|
||||
### Steps, Distance, Calories
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
users ||--o{ hc_raw_steps : "steps"
|
||||
users ||--o{ hc_raw_distance : "distance"
|
||||
users ||--o{ hc_raw_calories : "calories"
|
||||
health_connect_sync_logs ||--o{ hc_raw_steps : "batch"
|
||||
health_connect_sync_logs ||--o{ hc_raw_distance : "batch"
|
||||
health_connect_sync_logs ||--o{ hc_raw_calories : "batch"
|
||||
|
||||
hc_raw_steps {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string record_id
|
||||
string data_source
|
||||
string data_source_name
|
||||
datetime start_time
|
||||
datetime end_time
|
||||
datetime synced_at
|
||||
int count
|
||||
int sync_id FK
|
||||
}
|
||||
|
||||
hc_raw_distance {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string record_id
|
||||
string data_source
|
||||
string data_source_name
|
||||
datetime start_time
|
||||
datetime end_time
|
||||
datetime synced_at
|
||||
float distance_meters
|
||||
int sync_id FK
|
||||
}
|
||||
|
||||
hc_raw_calories {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string record_id
|
||||
string data_source
|
||||
string data_source_name
|
||||
datetime start_time
|
||||
datetime end_time
|
||||
datetime synced_at
|
||||
float calories
|
||||
string record_type
|
||||
int sync_id FK
|
||||
}
|
||||
```
|
||||
|
||||
### Heart Rate & HRV
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
users ||--o{ hc_raw_heart_rate : "records"
|
||||
users ||--o{ hc_raw_resting_hr : "resting"
|
||||
users ||--o{ hc_raw_hrv_rmssd : "hrv"
|
||||
hc_raw_heart_rate ||--o{ hc_raw_heart_rate_samples : "contains"
|
||||
|
||||
hc_raw_heart_rate {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string record_id
|
||||
string data_source
|
||||
string data_source_name
|
||||
datetime start_time
|
||||
datetime end_time
|
||||
datetime synced_at
|
||||
int sync_id FK
|
||||
}
|
||||
|
||||
hc_raw_heart_rate_samples {
|
||||
int id PK
|
||||
int record_id FK
|
||||
datetime time
|
||||
int bpm
|
||||
}
|
||||
|
||||
hc_raw_resting_hr {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string record_id
|
||||
string data_source
|
||||
string data_source_name
|
||||
datetime time
|
||||
datetime synced_at
|
||||
int bpm
|
||||
int sync_id FK
|
||||
}
|
||||
|
||||
hc_raw_hrv_rmssd {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string record_id
|
||||
string data_source
|
||||
string data_source_name
|
||||
datetime time
|
||||
datetime synced_at
|
||||
float rmssd
|
||||
int sync_id FK
|
||||
}
|
||||
```
|
||||
|
||||
### Sleep
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
users ||--o{ hc_raw_sleep_sessions : "sleeps"
|
||||
hc_raw_sleep_sessions ||--o{ hc_raw_sleep_stages : "stages"
|
||||
|
||||
hc_raw_sleep_sessions {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string record_id
|
||||
string data_source
|
||||
string data_source_name
|
||||
datetime start_time
|
||||
datetime end_time
|
||||
datetime synced_at
|
||||
string title
|
||||
text notes
|
||||
int sync_id FK
|
||||
}
|
||||
|
||||
hc_raw_sleep_stages {
|
||||
int id PK
|
||||
int session_id FK
|
||||
datetime start_time
|
||||
datetime end_time
|
||||
int stage_type
|
||||
string stage_name
|
||||
}
|
||||
```
|
||||
|
||||
### Body & Health Metrics
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
users ||--o{ hc_raw_weight : "weight"
|
||||
users ||--o{ hc_raw_height : "height"
|
||||
users ||--o{ hc_raw_body_fat : "bodyfat"
|
||||
users ||--o{ hc_raw_spo2 : "spo2"
|
||||
|
||||
hc_raw_weight {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string record_id
|
||||
string data_source
|
||||
string data_source_name
|
||||
datetime time
|
||||
datetime synced_at
|
||||
float weight_kg
|
||||
int sync_id FK
|
||||
}
|
||||
|
||||
hc_raw_height {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string record_id
|
||||
string data_source
|
||||
string data_source_name
|
||||
datetime time
|
||||
datetime synced_at
|
||||
float height_meters
|
||||
int sync_id FK
|
||||
}
|
||||
|
||||
hc_raw_body_fat {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string record_id
|
||||
string data_source
|
||||
string data_source_name
|
||||
datetime time
|
||||
datetime synced_at
|
||||
float percentage
|
||||
int sync_id FK
|
||||
}
|
||||
|
||||
hc_raw_spo2 {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string record_id
|
||||
string data_source
|
||||
string data_source_name
|
||||
datetime time
|
||||
datetime synced_at
|
||||
float percentage
|
||||
int sync_id FK
|
||||
}
|
||||
```
|
||||
|
||||
### Exercise, Nutrition & Hydration
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
users ||--o{ hc_raw_exercise_sessions : "exercises"
|
||||
users ||--o{ hc_raw_nutrition : "nutrition"
|
||||
users ||--o{ hc_raw_hydration : "hydration"
|
||||
|
||||
hc_raw_exercise_sessions {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string record_id
|
||||
string data_source
|
||||
string data_source_name
|
||||
datetime start_time
|
||||
datetime end_time
|
||||
datetime synced_at
|
||||
int exercise_type
|
||||
string exercise_type_name
|
||||
string title
|
||||
text notes
|
||||
float distance_meters
|
||||
float calories
|
||||
int avg_heart_rate
|
||||
int max_heart_rate
|
||||
int min_heart_rate
|
||||
int steps
|
||||
float elevation_gained_meters
|
||||
int sync_id FK
|
||||
}
|
||||
|
||||
hc_raw_nutrition {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string record_id
|
||||
string data_source
|
||||
string data_source_name
|
||||
datetime start_time
|
||||
datetime end_time
|
||||
datetime synced_at
|
||||
string name
|
||||
int meal_type
|
||||
float calories
|
||||
float protein_grams
|
||||
float carbohydrates_grams
|
||||
float fat_grams
|
||||
float fiber_grams
|
||||
float sugar_grams
|
||||
int sync_id FK
|
||||
}
|
||||
|
||||
hc_raw_hydration {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string record_id
|
||||
string data_source
|
||||
string data_source_name
|
||||
datetime start_time
|
||||
datetime end_time
|
||||
datetime synced_at
|
||||
float volume_liters
|
||||
int sync_id FK
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Résumé des Tables
|
||||
|
||||
| # | Table | Type | Description |
|
||||
|---|-------|------|-------------|
|
||||
| 1 | `users` | Core | Comptes utilisateurs |
|
||||
| 2 | `challenges` | Core | Défis/habitudes à suivre |
|
||||
| 3 | `tracking` | Core | Progression quotidienne des défis |
|
||||
| 4 | `daily_health_metrics` | Core | Métriques santé agrégées (legacy) |
|
||||
| 5 | `daily_context` | Core | Contexte subjectif (humeur, tags) |
|
||||
| 6 | `workout_sessions` | Core | Sessions d'entraînement manuelles |
|
||||
| 7 | `health_connect_sync_logs` | HC | Journal de synchronisation |
|
||||
| 8 | `health_connect_daily_metrics` | HC | Métriques quotidiennes Health Connect |
|
||||
| 9 | `health_connect_exercise_sessions` | HC | Sessions d'exercice Health Connect |
|
||||
| 10 | `hc_raw_steps` | Raw | Pas individuels |
|
||||
| 11 | `hc_raw_heart_rate` | Raw | Conteneurs de fréquence cardiaque |
|
||||
| 12 | `hc_raw_heart_rate_samples` | Raw | Échantillons de fréquence cardiaque |
|
||||
| 13 | `hc_raw_resting_hr` | Raw | Fréquence cardiaque au repos |
|
||||
| 14 | `hc_raw_sleep_sessions` | Raw | Sessions de sommeil |
|
||||
| 15 | `hc_raw_sleep_stages` | Raw | Phases de sommeil |
|
||||
| 16 | `hc_raw_distance` | Raw | Distance |
|
||||
| 17 | `hc_raw_calories` | Raw | Calories |
|
||||
| 18 | `hc_raw_spo2` | Raw | Saturation en oxygène |
|
||||
| 19 | `hc_raw_weight` | Raw | Poids |
|
||||
| 20 | `hc_raw_height` | Raw | Taille |
|
||||
| 21 | `hc_raw_body_fat` | Raw | Masse grasse |
|
||||
| 22 | `hc_raw_exercise_sessions` | Raw | Sessions d'exercice brutes |
|
||||
| 23 | `hc_raw_nutrition` | Raw | Nutrition |
|
||||
| 24 | `hc_raw_hydration` | Raw | Hydratation |
|
||||
| 25 | `hc_raw_hrv_rmssd` | Raw | Variabilité cardiaque (HRV) |
|
||||
|
||||
---
|
||||
|
||||
## Flux de Données
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Android Health Connect API] -->|Raw Records| B[Android Companion App]
|
||||
B -->|POST /api/health-connect/sync-raw| C[Backend FastAPI]
|
||||
C -->|Batch Insert| D[(hc_raw_* Tables)]
|
||||
D -->|AggregationService| E[health_connect_daily_metrics]
|
||||
D -->|Health Analytics API| F[/api/analytics/daily]
|
||||
D -->|Health Analytics API| G[/api/analytics/range]
|
||||
E -->|Legacy API| H[/api/health/stats]
|
||||
F --> I[Frontend Dashboard]
|
||||
G --> I
|
||||
H --> I
|
||||
|
||||
J[Zepp Export CSV] -->|Script Import| C
|
||||
C --> K[(daily_health_metrics)]
|
||||
C --> L[(workout_sessions)]
|
||||
K --> H
|
||||
L --> M[/api/health/workouts]
|
||||
M --> I
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Index & Contraintes
|
||||
|
||||
Toutes les tables raw incluent :
|
||||
- **Unique Constraint** sur `(user_id, record_id, data_source)` pour éviter les doublons
|
||||
- **Index** sur `(user_id, start_time)` ou `(user_id, time)` pour des requêtes rapides par période
|
||||
- **Foreign Key** vers `health_connect_sync_logs` pour la traçabilité
|
||||
- **Foreign Key** vers `users` pour l'isolation multi-utilisateurs
|
||||
@@ -1,416 +1,325 @@
|
||||
# HabitForge 🎯
|
||||
# 🏋️ HabitForge
|
||||
|
||||
HabitForge is a powerful, self-hosted habit tracking and gamification platform designed to help users build and maintain consistent routines. It combines a robust Python backend with a dynamic, modern frontend to provide a premium user experience.
|
||||
> Plateforme auto-hébergée de suivi d'habitudes, de santé et de fitness avec companion app Android
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
## 📖 Overview
|
||||
|
||||
HabitForge allows users to create custom challenges (daily, weekly, monthly), track their progress with detailed analytics, and stay motivated through gamification elements like badges and streaks. The application is built with a **Mobile-First** design philosophy, ensuring a seamless experience across all devices.
|
||||
|
||||
### Key Features
|
||||
|
||||
* **🏆 Gamification:** Earn badges for streaks, total reps, and consistency.
|
||||
* **📊 Analytics:** Visual charts (reps, completion rates) and consistency heatmaps.
|
||||
* **🔁 Flexible Challenges:** Support for Daily, Weekly (specific days), and Monthly targets.
|
||||
* **🧠 Smart Tracking:** Tracks reps, completion status, and optional notes per day.
|
||||
* **🌗 Dark Mode:** Fully supported dark/light themes with persistence.
|
||||
* **📱 Responsive UI:** Built with Tailwind CSS for a fluid experience on mobile and desktop.
|
||||
* **🔐 Authentication:** Secure JWT-based user authentication system.
|
||||
* **🖱️ Drag & Drop:** Reorder challenges easily to prioritize your focus.
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🛠 Tech Stack
|
||||
## 📖 Vue d'Ensemble
|
||||
|
||||
HabitForge est bien plus qu'un simple tracker d'habitudes. C'est une plateforme complète qui combine :
|
||||
|
||||
- 🎯 **Suivi d'habitudes** avec défis personnalisables (reps, minutes, km, pages...)
|
||||
- 📊 **Dashboard santé** connecté à Health Connect (Android) et Zepp/Amazfit
|
||||
- 📱 **Companion app Android** pour synchronisation automatique des données de santé
|
||||
- 🧠 **Analytics avancés** : readiness score, corrélations, tendances
|
||||
- 🏗️ **Architecture scalable** : SQLite pour le dev, PostgreSQL pour la prod
|
||||
|
||||
---
|
||||
|
||||
## ✨ Fonctionnalités
|
||||
|
||||
### 🎯 Challenges & Habitudes
|
||||
- **Défis flexibles** : quotidien, hebdomadaire (jours spécifiques), mensuel, annuel
|
||||
- **Multi-unités** : reps, minutes, pages, kilomètres
|
||||
- **Jours de repos** configurables
|
||||
- **15 exercices animés** (GIFs) comme références visuelles
|
||||
- **Icônes FontAwesome** personnalisables
|
||||
- **Drag & drop** pour réorganiser les priorités
|
||||
- **Statistiques** : streak, taux de complétion, reps totales
|
||||
- **Heatmap de consistance** (vue calendrier)
|
||||
|
||||
### 📊 Dashboard Santé
|
||||
- **Widgets interactifs** avec jauges semi-circulaires (Canvas API)
|
||||
- Steps quotidiens
|
||||
- Calories brûlées
|
||||
- Fréquence cardiaque (min/max/repos)
|
||||
- SpO2
|
||||
- Poids (lbs/kg) & BMI avec tendances
|
||||
- **Décomposition du sommeil** : profond, léger, REM, éveillé
|
||||
- **Graphiques d'historique** (Chart.js) : 7j, 30j, 365j
|
||||
- **Readiness Score** quotidien basé sur HRV, RHR et sommeil
|
||||
- **Contexte subjectif** : humeur, tags, notes
|
||||
|
||||
### 📱 Android Companion App
|
||||
- **Lecture native Health Connect** (tous les types de données)
|
||||
- **Sync automatique** configurable (1h, 3h, 6h, 12h, 24h)
|
||||
- **15 types de données brutes** synchronisées (steps, HR, sleep stages, SpO2, poids, nutrition...)
|
||||
- **Historique des synchronisations** avec stats détaillées
|
||||
- **Test de connexion** serveur avec temps de réponse
|
||||
- **Validation de schéma** des données avant sync
|
||||
- **Indicateur de statut** serveur en temps réel
|
||||
|
||||
### 🔄 Intégrations
|
||||
- **Health Connect** (Android) — sync native via companion app
|
||||
- **Zepp/Amazfit** — import CSV des données exportées
|
||||
- **Architecture Provider** — extensible pour futures sources (Google Fit, Apple Health, Garmin...)
|
||||
- **Agrégation on-demand** — calcul des métriques à partir des données brutes
|
||||
|
||||
### 🎨 UX/UI
|
||||
- **Mobile-First** design (Tailwind CSS)
|
||||
- **Dark Mode** avec persistance
|
||||
- **Jauges animées** Canvas pour poids et BMI
|
||||
- **Modales** pour détails des métriques
|
||||
- **Navigation par onglets** fluide
|
||||
|
||||
---
|
||||
|
||||
## 🛠 Stack Technique
|
||||
|
||||
### Backend
|
||||
* **Framework:** [FastAPI](https://fastapi.tiangolo.com/) (High performance, easy to learn)
|
||||
* **Database ORM:** [SQLAlchemy](https://www.sqlalchemy.org/)
|
||||
* **Database:** SQLite (Default, stored in `./data/habitforge.db`)
|
||||
* **Authentication:** OAuth2 with Password (and hashing via Argon2/Passlib)
|
||||
* **Schema Validation:** Pydantic Models
|
||||
| Composant | Technologie |
|
||||
|:---|:---|
|
||||
| Framework | FastAPI 0.141 |
|
||||
| ORM | SQLAlchemy 2.0 |
|
||||
| Auth | JWT (OAuth2 Password Flow) + Argon2 |
|
||||
| Validation | Pydantic 2.0 |
|
||||
| Rate Limiting | SlowAPI |
|
||||
| Migrations | Alembic |
|
||||
| Server | Uvicorn (dev) / Gunicorn + Uvicorn Workers (prod) |
|
||||
|
||||
### Frontend
|
||||
* **Core:** Vanilla JavaScript (ES6+)
|
||||
* **Styling:** [Tailwind CSS](https://tailwindcss.com/) (via CDN for simplicity)
|
||||
* **Icons:** FontAwesome 6
|
||||
* **Animations:** Anime.js
|
||||
* **Charts:** Chart.js
|
||||
* **Drag & Drop:** SortableJS
|
||||
| Composant | Technologie |
|
||||
|:---|:---|
|
||||
| Core | Vanilla JavaScript (ES6+) |
|
||||
| CSS | Tailwind CSS (CDN) |
|
||||
| Charts | Chart.js |
|
||||
| Icons | FontAwesome 6 |
|
||||
| Animations | Anime.js + Canvas API |
|
||||
| Drag & Drop | SortableJS |
|
||||
|
||||
### Android
|
||||
| Composant | Technologie |
|
||||
|:---|:---|
|
||||
| Langage | Kotlin |
|
||||
| HTTP Client | Retrofit |
|
||||
| Health SDK | Android Health Connect API |
|
||||
| UI | Jetpack + Material Design |
|
||||
| Auth | JWT token management |
|
||||
|
||||
### Infrastructure
|
||||
* **Containerization:** Docker & Docker Compose
|
||||
* **Server:** Uvicorn (ASGI)
|
||||
| Environnement | Configuration |
|
||||
|:---|:---|
|
||||
| Dev simple | `docker-compose.yml` — SQLite |
|
||||
| Dev complet | `docker-compose.dev.yml` — PostgreSQL + CloudBeaver |
|
||||
| Production | `docker-compose.prod.yml` — Nginx + Gunicorn + Backup auto |
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Getting Started
|
||||
## 🚀 Démarrage Rapide
|
||||
|
||||
### Prerequisites
|
||||
### Prérequis
|
||||
- Docker & Docker Compose
|
||||
- Git LFS (pour les GIFs)
|
||||
|
||||
Before you begin, ensure you have the following installed:
|
||||
* **Docker** and **Docker Compose**
|
||||
* **Python 3.9+** (if running locally without Docker)
|
||||
* **Google OAuth Credentials** (optional, for health metrics sync)
|
||||
|
||||
#### Environment Setup
|
||||
HabitForge uses environment variables for configuration.
|
||||
1. **Copy the example file:**
|
||||
```bash
|
||||
cp .env.example .env.development
|
||||
# Also create production if needed
|
||||
cp .env.example .env.production
|
||||
```
|
||||
2. **Edit the files:** Fill in your `SECRET_KEY` and Google API credentials.
|
||||
|
||||
---
|
||||
|
||||
### 🐳 Running with Docker (Recommended)
|
||||
|
||||
HabitForge provides several Docker Compose configurations depending on your needs:
|
||||
|
||||
#### 1. Simple Mode (SQLite)
|
||||
Perfect for a quick test or personal use with zero database configuration.
|
||||
### Dev complet (PostgreSQL + interface DB)
|
||||
```bash
|
||||
# Uses docker-compose.yml
|
||||
docker-compose up -d --build
|
||||
git clone https://git.dracodev.net/Projets/HabitForge.git
|
||||
cd HabitForge
|
||||
docker compose -f docker-compose.dev.yml up -d --build
|
||||
```
|
||||
* **Database:** SQLite stored in `./data/habitforge.db`
|
||||
* **Access:** `http://localhost:8000`
|
||||
|
||||
#### 2. Development Mode (PostgreSQL)
|
||||
Ideal for development with a robust database and hot-reloading enabled.
|
||||
```bash
|
||||
# Uses docker-compose.dev.yml
|
||||
docker-compose -f docker-compose.dev.yml up -d --build
|
||||
```
|
||||
* **Database:** PostgreSQL 15
|
||||
* **Features:** Auto-reload enabled in the backend.
|
||||
* **Access:** `http://localhost:8000`
|
||||
**Accès :**
|
||||
- 🌐 App : http://localhost:8000
|
||||
- 🗄️ CloudBeaver (DB GUI) : http://localhost:8978 (admin/admin)
|
||||
- 📖 API Docs : http://localhost:8000/docs
|
||||
|
||||
#### 3. Production Mode (Full Stack)
|
||||
The professional setup with security and performance in mind.
|
||||
### Mode simple (SQLite)
|
||||
```bash
|
||||
# Uses docker-compose.prod.yml
|
||||
docker-compose -f docker-compose.prod.yml up -d --build
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
### Production (Nginx + backup auto)
|
||||
```bash
|
||||
# Configurer .env.production d'abord
|
||||
docker compose -f docker-compose.prod.yml up -d --build
|
||||
```
|
||||
* **Components:**
|
||||
* **Nginx:** Reverse proxy with SSL/TLS support.
|
||||
* **Gunicorn:** Production-grade WSGI server with multiple workers.
|
||||
* **PostgreSQL:** Dedicated database container.
|
||||
* **Backup:** Automatic daily database backups to `./backups`.
|
||||
* **Access:** `http://localhost` (or your configured domain)
|
||||
|
||||
---
|
||||
|
||||
### 🐍 Local Development (Manual)
|
||||
## 📂 Structure du Projet
|
||||
|
||||
If you prefer to run the services directly on your machine:
|
||||
|
||||
1. **Set up Python Environment:**
|
||||
```bash
|
||||
python -m venv venv
|
||||
# Windows
|
||||
.\venv\Scripts\activate
|
||||
# Linux/Mac
|
||||
source venv/bin/activate
|
||||
```
|
||||
|
||||
2. **Install Dependencies:**
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
3. **Run the Server:**
|
||||
```bash
|
||||
# Ensure your .env file is present or env vars are set
|
||||
uvicorn backend.main:app --reload --host 0.0.0.0 --port 8000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📂 Project Structure
|
||||
|
||||
```plaintext
|
||||
```
|
||||
HabitForge/
|
||||
├── backend/ # Python FastAPI Backend (Modular Architecture)
|
||||
│ ├── api/v1/ # API Routes (Auth, Challenges, Health)
|
||||
│ ├── core/ # Configuration, Security, Dependencies
|
||||
│ ├── models/ # SQLAlchemy Database Models
|
||||
│ ├── schemas/ # Pydantic Validation Schemas
|
||||
│ ├── services/ # Business Logic Layer
|
||||
│ ├── repositories/ # Data Access Layer
|
||||
│ └── integrations/ # External APIs (Google Fit, Zepp)
|
||||
├── frontend/ # Static Frontend Assets
|
||||
│ ├── app.js # Main frontend logic
|
||||
│ └── index.html # Dashboard
|
||||
├── data/ # SQLite storage (if used)
|
||||
├── nginx/ # Nginx configuration and SSL certificates
|
||||
├── scripts/ # Database migrations and backup scripts
|
||||
├── docker-compose.yml # Simple SQLite configuration
|
||||
├── docker-compose.dev.yml # Development (Postgres) configuration
|
||||
└── docker-compose.prod.yml # Production (Nginx + Postgres + Backup) configuration
|
||||
├── backend/ # API FastAPI
|
||||
│ ├── api/v1/ # Routes REST
|
||||
│ │ ├── auth.py # Authentification JWT
|
||||
│ │ ├── challenges.py # CRUD Challenges + Tracking
|
||||
│ │ ├── health.py # Stats santé + Workouts
|
||||
│ │ ├── health_connect.py # Sync Health Connect (legacy)
|
||||
│ │ ├── health_connect_raw.py# Sync données brutes (15 types)
|
||||
│ │ └── health_analytics.py # Analytics + Readiness Score
|
||||
│ ├── core/config.py # Configuration (pydantic-settings)
|
||||
│ ├── models/ # 25 modèles SQLAlchemy
|
||||
│ │ ├── user.py # Comptes utilisateurs
|
||||
│ │ ├── challenge.py # Défis
|
||||
│ │ ├── tracking.py # Suivi quotidien
|
||||
│ │ ├── daily_health_metrics.py # Métriques agrégées legacy
|
||||
│ │ ├── daily_context.py # Contexte subjectif (mood)
|
||||
│ │ ├── workout_session.py # Sessions manuelles
|
||||
│ │ ├── health_connect.py # Sync logs + métriques HC
|
||||
│ │ └── health_connect_raw.py# 15 tables raw HC
|
||||
│ ├── services/ # Couche métier
|
||||
│ │ ├── auth_service.py
|
||||
│ │ ├── challenge_service.py
|
||||
│ │ ├── health_service.py
|
||||
│ │ └── aggregation_service.py # Agrégation on-demand
|
||||
│ ├── integrations/ # Providers données santé
|
||||
│ │ ├── health_provider.py # Interface abstraite
|
||||
│ │ ├── health_connect_provider.py
|
||||
│ │ └── import_zepp.py # Import CSV Zepp
|
||||
│ ├── schemas/ # Validation Pydantic
|
||||
│ ├── repositories/ # Data access layer
|
||||
│ └── database.py # Engine + Session
|
||||
├── frontend/ # SPA vanilla JS
|
||||
│ ├── index.html # Dashboard principal
|
||||
│ ├── login.html # Page login
|
||||
│ ├── app.js # Logique applicative (4300+ lignes)
|
||||
│ └── static/ # 15 GIFs d'exercices (LFS)
|
||||
├── android-companion/ # App Android Kotlin
|
||||
│ └── app/src/main/java/com/habitforge/companion/
|
||||
│ ├── MainActivity.kt # UI principale
|
||||
│ ├── HealthConnectManager.kt # Lecture Health Connect
|
||||
│ ├── SyncService.kt # Service background
|
||||
│ ├── RawDataSyncService.kt# Sync données brutes
|
||||
│ ├── HabitForgeApi.kt # Client Retrofit
|
||||
│ └── ... # 17 fichiers Kotlin au total
|
||||
├── alembic/ # Migrations DB (9 versions)
|
||||
├── nginx/ # Config Nginx + SSL
|
||||
├── scripts/ # Utilitaires
|
||||
│ ├── import_zepp_data.py # Import données Zepp
|
||||
│ ├── migrate_to_postgres.py # Migration SQLite → PostgreSQL
|
||||
│ └── backup_db.sh # Backup automatique PostgreSQL
|
||||
├── docker-compose.yml # Dev simple (SQLite)
|
||||
├── docker-compose.dev.yml # Dev complet (PostgreSQL + CloudBeaver)
|
||||
├── docker-compose.prod.yml # Production (Nginx + Gunicorn + Backup)
|
||||
├── Dockerfile # Image Python 3.10-slim
|
||||
├── requirements.txt # Dépendances Python
|
||||
├── DATABASE_SCHEMA.md # Schémas Mermaid
|
||||
└── ROADMAP.md # Roadmap & état du projet
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔌 API Documentation
|
||||
## 🔌 API — Principaux Endpoints
|
||||
|
||||
Once the server is running, you can access the automatic interactive API documentation provided by Swagger UI:
|
||||
* **Docs:** `http://localhost:8000/docs`
|
||||
* **Redoc:** `http://localhost:8000/redoc`
|
||||
| Méthode | Endpoint | Description |
|
||||
|:---|:---|:---|
|
||||
| `POST` | `/api/auth/register` | Créer un compte |
|
||||
| `POST` | `/api/auth/token` | Obtenir un JWT |
|
||||
| `POST` | `/api/auth/refresh` | Rafraîchir le JWT |
|
||||
| `GET` | `/api/auth/me` | Profil utilisateur |
|
||||
| `GET/POST/PUT/DELETE` | `/api/challenges[/{id}]` | CRUD Challenges |
|
||||
| `POST` | `/api/tracking` | Logger une répétition |
|
||||
| `GET` | `/api/health` | Health check DB |
|
||||
| `GET` | `/api/health/stats` | Statistiques santé (période) |
|
||||
| `GET` | `/api/health/workouts` | Sessions d'entraînement |
|
||||
| `POST` | `/api/health-connect/sync-raw` | Sync données brutes (15 types) |
|
||||
| `GET` | `/api/analytics/daily` | Analytics quotidien (avec readiness) |
|
||||
| `GET` | `/api/analytics/range` | Analytics plage de dates |
|
||||
| `POST` | `/api/analytics/context` | Mise à jour mood/tags |
|
||||
|
||||
### Core Endpoints
|
||||
* **Auth:** `/api/auth/register`, `/api/auth/token`
|
||||
* **Challenges:**
|
||||
* `GET /api/challenges`: List all user challenges
|
||||
* `POST /api/challenges`: Create new challenge
|
||||
* `PUT /api/challenges/reorder`: Update display order
|
||||
* **Tracking:**
|
||||
* `POST /api/tracking`: Log reps/completion for a date
|
||||
📖 **Documentation interactive** : http://localhost:8000/docs (Swagger) | http://localhost:8000/redoc
|
||||
|
||||
---
|
||||
|
||||
## 📊 Schéma de Base de Données
|
||||
|
||||
Le projet contient **25 tables** organisées en 3 couches :
|
||||
|
||||
| Couche | Tables | Description |
|
||||
|:---|:---:|:---|
|
||||
| **Core** | 6 | users, challenges, tracking, daily_health_metrics, daily_context, workout_sessions |
|
||||
| **Health Connect Aggregated** | 3 | sync_logs, daily_metrics, exercise_sessions |
|
||||
| **Health Connect Raw** | 15 | steps, heart_rate + samples, resting_hr, sleep_sessions + stages, distance, calories, spo2, weight, height, body_fat, exercise_sessions, nutrition, hydration, hrv_rmssd |
|
||||
|
||||
➡️ Voir [`DATABASE_SCHEMA.md`](./DATABASE_SCHEMA.md) pour les diagrammes Mermaid complets.
|
||||
|
||||
---
|
||||
|
||||
## 🗺️ Roadmap
|
||||
|
||||
➡️ Voir [`ROADMAP.md`](./ROADMAP.md) pour l'état détaillé des fonctionnalités et la vision future.
|
||||
|
||||
### Priorités actuelles
|
||||
- 🔴 Tests automatisés (pytest)
|
||||
- 🔴 Cache d'agrégation (performances)
|
||||
- 🟡 Badges & Achievements
|
||||
- 🟡 Export de données
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Configuration
|
||||
|
||||
All configuration is managed via Environment Variables or a `.env` file.
|
||||
Copier le fichier d'exemple et adapter :
|
||||
|
||||
| Variable | Description | Default |
|
||||
| :--- | :--- | :--- |
|
||||
| `SECRET_KEY` | Key for JWT encryption | *Required* |
|
||||
| `DATABASE_URL` | SQLAlchemy connection string | `sqlite:///./data/habitforge.db` |
|
||||
| `CORS_ORIGINS` | Allowed origins for API | `http://localhost:8000` |
|
||||
| `GOOGLE_CLIENT_ID` | Google OAuth Client ID | `""` |
|
||||
| `GOOGLE_CLIENT_SECRET` | Google OAuth Client Secret | `""` |
|
||||
```bash
|
||||
cp .env.example .env.development
|
||||
```
|
||||
|
||||
### Variables principales
|
||||
|
||||
| Variable | Description | Défaut |
|
||||
|:---|:---|:---|
|
||||
| `SECRET_KEY` | Clé de chiffrement JWT | *À définir* |
|
||||
| `DATABASE_URL` | Chaîne de connexion DB | `sqlite:///./data/habitforge.db` |
|
||||
| `CORS_ORIGINS` | Origines autorisées | `http://localhost:8000` |
|
||||
| `GOOGLE_CLIENT_ID` | OAuth Google | `""` |
|
||||
| `HEALTH_PROVIDER` | Provider santé | `"health_connect"` |
|
||||
| `RATE_LIMIT_ENABLED` | Rate limiting | `true` |
|
||||
| `DEBUG` | Mode debug | `true` |
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Google OAuth Setup (Health Metrics Integration)
|
||||
## 📱 Companion App Android
|
||||
|
||||
To enable Google Fit integration for health metrics tracking, you need to create OAuth 2.0 credentials in the Google Cloud Console.
|
||||
|
||||
### Step 1: Create a Google Cloud Project
|
||||
|
||||
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
|
||||
2. Click **"Select a project"** → **"New Project"**
|
||||
3. Enter a project name (e.g., "HabitForge")
|
||||
4. Click **"Create"**
|
||||
|
||||
### Step 2: Enable Required APIs
|
||||
|
||||
1. In your project, navigate to **"APIs & Services"** → **"Library"**
|
||||
2. Search for and enable the following APIs:
|
||||
- **Google Fitness API**
|
||||
- **Google OAuth2 API** (usually enabled by default)
|
||||
|
||||
### Step 3: Configure OAuth Consent Screen
|
||||
|
||||
1. Go to **"APIs & Services"** → **"OAuth consent screen"**
|
||||
2. Select **"External"** (unless you have a Google Workspace)
|
||||
3. Fill in the required information:
|
||||
- **App name:** HabitForge
|
||||
- **User support email:** Your email
|
||||
- **Developer contact:** Your email
|
||||
4. Click **"Save and Continue"**
|
||||
5. **Scopes:** Click **"Add or Remove Scopes"** and add:
|
||||
- `.../auth/fitness.activity.read`
|
||||
- `.../auth/fitness.body.read`
|
||||
- `.../auth/fitness.heart_rate.read`
|
||||
- `.../auth/fitness.sleep.read`
|
||||
6. Click **"Save and Continue"**
|
||||
7. **Test users:** Add your Google account email (for testing)
|
||||
8. Click **"Save and Continue"**
|
||||
|
||||
### Step 4: Create OAuth 2.0 Credentials
|
||||
|
||||
1. Go to **"APIs & Services"** → **"Credentials"**
|
||||
2. Click **"+ Create Credentials"** → **"OAuth client ID"**
|
||||
3. Select **"Web application"**
|
||||
4. Configure:
|
||||
- **Name:** HabitForge Web Client
|
||||
- **Authorized JavaScript origins:**
|
||||
```
|
||||
http://localhost:8000
|
||||
https://yourdomain.com
|
||||
```
|
||||
- **Authorized redirect URIs:**
|
||||
```
|
||||
http://localhost:8000/api/google/callback
|
||||
https://yourdomain.com/api/google/callback
|
||||
```
|
||||
5. Click **"Create"**
|
||||
6. **Copy your credentials:**
|
||||
- `GOOGLE_CLIENT_ID`: The Client ID (looks like `xxxxx.apps.googleusercontent.com`)
|
||||
- `GOOGLE_CLIENT_SECRET`: The Client Secret
|
||||
|
||||
### Step 5: Update Your .env File
|
||||
|
||||
Add the credentials to your `.env` file:
|
||||
L'application Android se synchronise avec votre instance HabitForge pour importer automatiquement vos données Health Connect.
|
||||
|
||||
### Build
|
||||
```bash
|
||||
GOOGLE_CLIENT_ID=your-client-id-here.apps.googleusercontent.com
|
||||
GOOGLE_CLIENT_SECRET=your-client-secret-here
|
||||
cd android-companion
|
||||
./gradlew assembleDebug
|
||||
# APK dans app/build/outputs/apk/debug/
|
||||
```
|
||||
|
||||
### Step 6: Test the Integration
|
||||
### Données synchronisées
|
||||
Steps • Distance • Calories • Fréquence cardiaque • FC repos • Sommeil (phases) • SpO2 • Poids • Taille • Masse grasse • Sessions d'exercice • Nutrition • Hydratation • HRV
|
||||
|
||||
1. Restart your application
|
||||
2. Navigate to the Health Dashboard
|
||||
3. Click the **"Sync"** button
|
||||
4. Authorize HabitForge to access your Google Fit data
|
||||
5. Data should sync automatically
|
||||
➡️ Voir [`android-companion/README.md`](./android-companion/README.md) pour la documentation complète.
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ Database Configuration
|
||||
## 📥 Import Zepp/Amazfit
|
||||
|
||||
HabitForge supports two database backends: **SQLite** (default, simple) and **PostgreSQL** (production-ready).
|
||||
Si vous utilisez une montre Zepp/Amazfit, vous pouvez importer vos données :
|
||||
|
||||
### Option 1: SQLite (Default - Recommended for Personal Use)
|
||||
|
||||
SQLite requires **no additional setup** and is perfect for single-user deployments.
|
||||
|
||||
**Configuration:**
|
||||
```bash
|
||||
# .env file
|
||||
DATABASE_URL=sqlite:///./data/habitforge.db
|
||||
# Placer l'export dans export-zepp/
|
||||
docker compose -f docker-compose.dev.yml exec web python scripts/import_zepp_data.py
|
||||
```
|
||||
|
||||
**Characteristics:**
|
||||
- ✅ Zero configuration required
|
||||
- ✅ File-based (stored in `./data/habitforge.db`)
|
||||
- ✅ Perfect for personal use
|
||||
- ✅ Automatic backups via file copy
|
||||
- ⚠️ Not recommended for high-concurrency scenarios
|
||||
|
||||
**Docker Compose:**
|
||||
```bash
|
||||
# Uses SQLite by default
|
||||
docker-compose up -d --build
|
||||
```
|
||||
|
||||
### Option 2: PostgreSQL (Recommended for Production)
|
||||
|
||||
PostgreSQL provides better performance, concurrency, and scalability.
|
||||
|
||||
#### A. Using Docker Compose (Easiest)
|
||||
|
||||
**Development Mode:**
|
||||
```bash
|
||||
# Uses docker-compose.dev.yml with PostgreSQL
|
||||
docker-compose -f docker-compose.dev.yml up -d --build
|
||||
```
|
||||
|
||||
**Production Mode:**
|
||||
```bash
|
||||
# Uses docker-compose.prod.yml with PostgreSQL + Nginx
|
||||
docker-compose -f docker-compose.prod.yml up -d --build
|
||||
```
|
||||
|
||||
The database credentials are configured in the respective `docker-compose` files.
|
||||
|
||||
#### B. Using External PostgreSQL Server
|
||||
|
||||
If you have an existing PostgreSQL server:
|
||||
|
||||
1. **Create a database:**
|
||||
```sql
|
||||
CREATE DATABASE habitforge;
|
||||
CREATE USER habitforge_user WITH PASSWORD 'your_secure_password';
|
||||
GRANT ALL PRIVILEGES ON DATABASE habitforge TO habitforge_user;
|
||||
```
|
||||
|
||||
2. **Configure DATABASE_URL:**
|
||||
```bash
|
||||
# .env file
|
||||
DATABASE_URL=postgresql://habitforge_user:your_secure_password@localhost:5432/habitforge
|
||||
```
|
||||
|
||||
**Format:**
|
||||
```
|
||||
postgresql://[username]:[password]@[host]:[port]/[database_name]
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
```bash
|
||||
# Local PostgreSQL
|
||||
DATABASE_URL=postgresql://postgres:password@localhost:5432/habitforge
|
||||
|
||||
# Remote PostgreSQL
|
||||
DATABASE_URL=postgresql://user:[email protected]:5432/habitforge
|
||||
|
||||
# With SSL
|
||||
DATABASE_URL=postgresql://user:[email protected]:5432/habitforge?sslmode=require
|
||||
```
|
||||
|
||||
3. **Run migrations:**
|
||||
```bash
|
||||
alembic upgrade head
|
||||
```
|
||||
|
||||
#### C. PostgreSQL on Cloud Providers
|
||||
|
||||
**Heroku Postgres:**
|
||||
```bash
|
||||
DATABASE_URL=postgresql://user:[email protected]:5432/dbname
|
||||
```
|
||||
|
||||
**AWS RDS:**
|
||||
```bash
|
||||
DATABASE_URL=postgresql://username:[email protected]:5432/habitforge
|
||||
```
|
||||
|
||||
**Google Cloud SQL:**
|
||||
```bash
|
||||
DATABASE_URL=postgresql://user:pass@/dbname?host=/cloudsql/project:region:instance
|
||||
```
|
||||
|
||||
**DigitalOcean Managed Database:**
|
||||
```bash
|
||||
DATABASE_URL=postgresql://user:[email protected]:25060/habitforge?sslmode=require
|
||||
```
|
||||
|
||||
### Switching Between Databases
|
||||
|
||||
To switch from SQLite to PostgreSQL (or vice versa):
|
||||
|
||||
1. **Update DATABASE_URL** in your `.env` file
|
||||
2. **Run migrations:**
|
||||
```bash
|
||||
alembic upgrade head
|
||||
```
|
||||
3. **Restart the application:**
|
||||
```bash
|
||||
docker-compose down
|
||||
docker-compose up -d --build
|
||||
```
|
||||
|
||||
**Note:** Data is **not automatically migrated** between databases. You'll need to export/import data manually if switching with existing data.
|
||||
➡️ Voir [`ZEPP_IMPORT.md`](./ZEPP_IMPORT.md) pour les détails.
|
||||
|
||||
---
|
||||
|
||||
### Database Migrations
|
||||
The project includes Alembic for database version control.
|
||||
```bash
|
||||
alembic upgrade head
|
||||
```
|
||||
## 🤝 Contribuer
|
||||
|
||||
1. Fork le projet
|
||||
2. Branche feature : `git checkout -b feature/AmazingFeature`
|
||||
3. Commit : `git commit -m 'Add AmazingFeature'`
|
||||
4. Push : `git push origin feature/AmazingFeature`
|
||||
5. Pull Request
|
||||
|
||||
Le projet utilise **ruff** pour le linting Python et **pre-commit** pour les hooks.
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Contributing
|
||||
## 📄 Licence
|
||||
|
||||
Contributions are welcome!
|
||||
1. Fork the project.
|
||||
2. Create your feature branch (`git checkout -b feature/AmazingFeature`).
|
||||
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`).
|
||||
4. Push to the branch (`git push origin feature/AmazingFeature`).
|
||||
5. Open a Pull Request.
|
||||
|
||||
---
|
||||
|
||||
## 📄 License
|
||||
|
||||
Distributed under the MIT License. See `LICENSE` for more information.
|
||||
MIT License — voir le fichier `LICENSE`.
|
||||
|
||||
+267
@@ -0,0 +1,267 @@
|
||||
# 🗺️ HabitForge - Roadmap
|
||||
|
||||
> État des lieux et vision future du projet
|
||||
|
||||
---
|
||||
|
||||
## 📋 Ce qui est fait ✅
|
||||
|
||||
### 🏗️ Infrastructure
|
||||
|
||||
| Fonctionnalité | Statut | Détails |
|
||||
|:---|:---:|:---|
|
||||
| Docker (simple SQLite) | ✅ | `docker-compose.yml` - déploiement rapide |
|
||||
| Docker Dev (PostgreSQL + CloudBeaver) | ✅ | `docker-compose.dev.yml` - DB admin UI |
|
||||
| Docker Prod (Nginx + Gunicorn + Backup) | ✅ | `docker-compose.prod.yml` - prêt production |
|
||||
| Environnements (.env) | ✅ | `.env.development`, `.env.staging`, `.env.production` |
|
||||
| Alembic Migrations | ✅ | 9 migrations, support SQLite & PostgreSQL |
|
||||
| Rate Limiting | ✅ | SlowAPI avec config par env |
|
||||
| Git LFS | ✅ | GIFs des exercices stockés via LFS |
|
||||
|
||||
### 🔐 Authentification
|
||||
|
||||
| Fonctionnalité | Statut | Détails |
|
||||
|:---|:---:|:---|
|
||||
| JWT Auth (OAuth2 Password Flow) | ✅ | Access + Refresh tokens |
|
||||
| Registration | ✅ | `POST /api/auth/register` |
|
||||
| Login | ✅ | `POST /api/auth/token` |
|
||||
| Token Refresh | ✅ | `POST /api/auth/refresh` |
|
||||
| Password Hashing (Argon2) | ✅ | Passlib + argon2-cffi |
|
||||
| Google OAuth (configuré) | ✅ | Client ID/Secret dans config |
|
||||
|
||||
### 🎯 Challenges & Tracking (Core)
|
||||
|
||||
| Fonctionnalité | Statut | Détails |
|
||||
|:---|:---:|:---|
|
||||
| CRUD Challenges | ✅ | Création, lecture, modification, suppression |
|
||||
| Types de périodes | ✅ | Jour, Semaine, Mois, Année |
|
||||
| Unités variées | ✅ | reps, minutes, pages, km |
|
||||
| Jours de repos | ✅ | Configuration par défi |
|
||||
| Fréquence custom | ✅ | Jours spécifiques de la semaine |
|
||||
| Icônes (FontAwesome) | ✅ | 15+ icônes disponibles |
|
||||
| Images d'exercice (GIFs) | ✅ | 15 exercices animés |
|
||||
| Descriptions | ✅ | Texte descriptif par défi |
|
||||
| Réordonnancement (Drag & Drop) | ✅ | SortableJS |
|
||||
| Suivi quotidien | ✅ | Reps, completed, notes |
|
||||
| Statistiques | ✅ | Reps totales, streak, taux de complétion |
|
||||
| Heatmap de consistance | ✅ | Vue calendrier |
|
||||
|
||||
### 📊 Health Dashboard
|
||||
|
||||
| Fonctionnalité | Statut | Détails |
|
||||
|:---|:---:|:---|
|
||||
| Métriques quotidiennes | ✅ | Steps, calories, distance, sleep, HR, SpO2 |
|
||||
| Widgets Weight & BMI | ✅ | Jauges semi-circulaires Canvas |
|
||||
| Graphiques d'historique | ✅ | Chart.js (7j, 30j, 365j) |
|
||||
| Périodes (day/week/month/year) | ✅ | Navigation par date |
|
||||
| Sessions d'entraînement | ✅ | Liste + résumé par type |
|
||||
| Contexte utilisateur | ✅ | Mood score, tags, notes |
|
||||
|
||||
### 📱 Android Companion App
|
||||
|
||||
| Fonctionnalité | Statut | Détails |
|
||||
|:---|:---:|:---|
|
||||
| Lecture Health Connect | ✅ | Tous les types de données supportés |
|
||||
| Sync manuelle | ✅ | Bouton Sync Now |
|
||||
| Auto-sync configurable | ✅ | 1h, 3h, 6h, 12h, 24h |
|
||||
| Authentification JWT | ✅ | Mêmes credentials que le web |
|
||||
| Historique des syncs | ✅ | Succès/échec, compteurs |
|
||||
| Test de connexion serveur | ✅ | Ping + temps de réponse |
|
||||
| Validation schéma données | ✅ | DataCompatibilityValidator |
|
||||
| Indicateur statut serveur | ✅ | Online/Auth/Timeout/Offline |
|
||||
| Configuration serveur | ✅ | URL + credentials |
|
||||
|
||||
### 🔄 Intégrations & Data Pipeline
|
||||
|
||||
| Fonctionnalité | Statut | Détails |
|
||||
|:---|:---:|:---|
|
||||
| Health Connect → Raw Storage | ✅ | 15 tables raw avec déduplication |
|
||||
| Raw → Aggregation Service | ✅ | Agrégation on-demand par jour/semaine/mois |
|
||||
| Health Analytics API | ✅ | `/api/analytics/daily`, `/api/analytics/range` |
|
||||
| Readiness Score | ✅ | Score mental + physique avec recommandations |
|
||||
| Source filtering | ✅ | Filtrage par source de données |
|
||||
| Zepp Data Import | ✅ | Script CSV → DB (activité, sommeil, HR, workouts) |
|
||||
| Provider abstraction | ✅ | HealthProviderFactory (extensible) |
|
||||
| Sync logs | ✅ | Traçabilité complète des batchs |
|
||||
|
||||
### 🎨 Frontend
|
||||
|
||||
| Fonctionnalité | Statut | Détails |
|
||||
|:---|:---:|:---|
|
||||
| Design Mobile-First | ✅ | Tailwind CSS responsive |
|
||||
| Dark Mode | ✅ | Toggle avec persistance localStorage |
|
||||
| Jauges Canvas | ✅ | Animations semi-circulaires |
|
||||
| Graphiques Chart.js | ✅ | Steps, calories, HR, poids |
|
||||
| Drag & Drop | ✅ | Réordonnancement challenges |
|
||||
| Modal détails métriques | ✅ | Weight/BMI détaillé |
|
||||
| Page login | ✅ | Auth + redirection |
|
||||
| Navigation par onglets | ✅ | Challenges, Health, Settings |
|
||||
|
||||
---
|
||||
|
||||
## 🚧 En cours / Planifié
|
||||
|
||||
### Phase 2 — Améliorations Core (Priorité Haute)
|
||||
|
||||
| Fonctionnalité | Priorité | Notes |
|
||||
|:---|:---:|:---|
|
||||
| **UX Onboarding** | 🔴 P0 | Wizard de bienvenue, premier challenge, connexion appareil |
|
||||
| **Tests automatisés** | 🔴 P0 | pytest pour backend, tests API, tests modèles |
|
||||
| **Validation Pydantic stricte** | 🔴 P0 | Schémas request/response complets |
|
||||
| **Gestion d'erreurs frontend** | 🔴 P0 | Toasts, retry, messages utilisateur |
|
||||
| **Cache d'agrégation** | 🟡 P1 | Redis ou cache DB pour les requêtes analytics |
|
||||
| **CI/CD Pipeline** | 🟡 P1 | GitHub Actions: lint, test, build docker |
|
||||
| **Seed data / Fixtures** | 🟡 P1 | Données de démo pour nouveaux utilisateurs |
|
||||
|
||||
### Phase 3 — Santé & Analytics (Priorité Haute)
|
||||
|
||||
| Fonctionnalité | Priorité | Notes |
|
||||
|:---|:---:|:---|
|
||||
| **Corrélations santé/habitudes** | 🔴 P0 | Impact du sommeil/steps sur la complétion des défis |
|
||||
| **Dashboard unifié** | 🔴 P0 | Challenges + Santé sur une seule vue |
|
||||
| **Rapports hebdomadaires** | 🟡 P1 | Email ou résumé in-app |
|
||||
| **Export données** | 🟡 P1 | CSV/JSON de toutes les métriques |
|
||||
| **Objectifs de santé** | 🟡 P1 | Cibles steps, sommeil, calories |
|
||||
| **Alertes / Notifications** | 🟢 P2 | Web push ou email pour streaks, objectifs |
|
||||
| **ML Scoring avancé** | 🟢 P2 | Prédictions de readiness, recommandations personnalisées |
|
||||
|
||||
### Phase 4 — Social & Gamification
|
||||
|
||||
| Fonctionnalité | Priorité | Notes |
|
||||
|:---|:---:|:---|
|
||||
| **Badges & Achievements** | 🟡 P1 | Badges par streak, total reps, milestones |
|
||||
| **Niveaux / XP** | 🟢 P2 | Système de progression |
|
||||
| **Classements** | 🟢 P2 | Leaderboards entre amis |
|
||||
| **Partage social** | 🟢 P2 | Partage de réussites |
|
||||
| **Défis de groupe** | 🔵 P3 | Défis multi-utilisateurs |
|
||||
|
||||
### Phase 5 — Mobile & Plateforme
|
||||
|
||||
| Fonctionnalité | Priorité | Notes |
|
||||
|:---|:---:|:---|
|
||||
| **Google Play Store** | 🟡 P1 | Publication companion app |
|
||||
| **iOS Companion (Swift/KMP)** | 🔵 P3 | Application iOS native ou KMP |
|
||||
| **PWA** | 🟡 P1 | Service worker, notifications push, offline |
|
||||
| **Multi-langue (i18n)** | 🟢 P2 | Support FR/EN minimum |
|
||||
| **Admin panel** | 🔵 P3 | Gestion utilisateurs, monitoring |
|
||||
|
||||
### Phase 6 — Infrastructure
|
||||
|
||||
| Fonctionnalité | Priorité | Notes |
|
||||
|:---|:---:|:---|
|
||||
| **Health endpoint monitoring** | 🟡 P1 | Prometheus + Grafana |
|
||||
| **DB Connection pooling** | 🟡 P1 | Optimisation PostgreSQL |
|
||||
| **CDN pour assets statiques** | 🟢 P2 | GIFs, CSS, JS |
|
||||
| **Kubernetes Helm chart** | 🔵 P3 | Déploiement scalable |
|
||||
| **Multi-tenant** | 🔵 P3 | Isolation par organisation |
|
||||
|
||||
---
|
||||
|
||||
## 📐 Architecture Actuelle
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ FRONTEND (SPA) │
|
||||
│ Vanilla JS + Tailwind CSS + Chart.js + SortableJS │
|
||||
│ Canvas Gauges • Dark Mode • Mobile-First │
|
||||
└─────────────────┬───────────────────────────────────────┘
|
||||
│ REST API (JWT)
|
||||
┌─────────────────▼───────────────────────────────────────┐
|
||||
│ BACKEND (FastAPI) │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────┐ │
|
||||
│ │ Auth │ │Challenges│ │ Health │ │ Analytics │ │
|
||||
│ │ /api/auth│ │/api/chal-│ │ /api/ │ │ /api/ │ │
|
||||
│ │ │ │ lenges │ │ health* │ │ analytics │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └────────────┘ │
|
||||
│ ┌──────────────────────────────────────────────────────┐│
|
||||
│ │ Health Connect API ││
|
||||
│ │ /api/health-connect/sync • /sync-raw • Raw Storage ││
|
||||
│ └──────────────────────────────────────────────────────┘│
|
||||
│ ┌──────────────────────────────────────────────────────┐│
|
||||
│ │ Service Layer ││
|
||||
│ │ AuthService • AggregationService • HealthProvider ││
|
||||
│ └──────────────────────────────────────────────────────┘│
|
||||
└─────────────────┬───────────────────────────────────────┘
|
||||
│ SQLAlchemy ORM
|
||||
┌─────────────────▼───────────────────────────────────────┐
|
||||
│ DATABASE (PostgreSQL / SQLite) │
|
||||
│ │
|
||||
│ 6 Core Tables │ 3 HC Aggregated │ 15 HC Raw Tables │
|
||||
│ users │ sync_logs │ hc_raw_steps │
|
||||
│ challenges │ daily_metrics │ hc_raw_heart_* │
|
||||
│ tracking │ exercise_sessions│ hc_raw_sleep_* │
|
||||
│ daily_health_* │ │ hc_raw_spo2... │
|
||||
│ daily_context │ │ (15 total) │
|
||||
│ workout_sess. │ │ │
|
||||
└─────────────────┬───────────────────────────────────────┘
|
||||
│
|
||||
┌─────────────────▼───────────────────────────────────────┐
|
||||
│ ANDROID COMPANION APP │
|
||||
│ Health Connect API → Raw Records → POST /sync-raw │
|
||||
│ Kotlin • Retrofit • Jetpack • Health Connect SDK │
|
||||
│ Auto-sync • Sync History • Connection Test │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧩 API Endpoints
|
||||
|
||||
| Méthode | Endpoint | Description |
|
||||
|:---|:---|:---|
|
||||
| `POST` | `/api/auth/register` | Créer un compte |
|
||||
| `POST` | `/api/auth/token` | Login (JWT) |
|
||||
| `POST` | `/api/auth/refresh` | Rafraîchir le token |
|
||||
| `GET` | `/api/auth/me` | Profil utilisateur |
|
||||
| `GET` | `/api/challenges` | Liste des défis |
|
||||
| `POST` | `/api/challenges` | Créer un défi |
|
||||
| `PUT` | `/api/challenges/{id}` | Modifier un défi |
|
||||
| `DELETE` | `/api/challenges/{id}` | Supprimer un défi |
|
||||
| `PUT` | `/api/challenges/reorder` | Réordonner |
|
||||
| `POST` | `/api/tracking` | Logger une répétition |
|
||||
| `GET` | `/api/tracking/{challenge_id}` | Historique tracking |
|
||||
| `GET` | `/api/health` | Health check |
|
||||
| `GET` | `/api/health/stats` | Stats de santé (période) |
|
||||
| `GET` | `/api/health/workouts` | Liste workouts |
|
||||
| `GET` | `/api/health/workouts/summary` | Résumé workouts |
|
||||
| `POST` | `/api/health-connect/sync` | Sync Health Connect (legacy) |
|
||||
| `POST` | `/api/health-connect/sync-raw` | Sync données brutes |
|
||||
| `GET` | `/api/health-connect/sync/status` | Statut sync |
|
||||
| `GET` | `/api/analytics/daily` | Analytics quotidien |
|
||||
| `GET` | `/api/analytics/range` | Analytics plage de dates |
|
||||
| `POST` | `/api/analytics/context` | Mise à jour contexte (mood) |
|
||||
| `GET` | `/api/analytics/sources` | Sources de données disponibles |
|
||||
| `GET` | `/api/static/images` | Liste images disponibles |
|
||||
|
||||
---
|
||||
|
||||
## 🔑 Choix Techniques
|
||||
|
||||
| Domaine | Choix | Raison |
|
||||
|:---|:---|:---|
|
||||
| Backend | FastAPI | Performance async, Swagger auto, validation Pydantic |
|
||||
| ORM | SQLAlchemy 2.0 | Maturité, flexibilité SQLite/PostgreSQL |
|
||||
| Auth | JWT + Argon2 | Stateless, sécurisé, standard OAuth2 |
|
||||
| Frontend | Vanilla JS + Tailwind | Zéro build step, rapide, Tailwind CDN |
|
||||
| Charts | Chart.js | Léger, bonne API, canvas performant |
|
||||
| Mobile | Kotlin natif | Accès direct Health Connect SDK Android |
|
||||
| DB | PostgreSQL (prod) / SQLite (dev) | Flexibilité selon environnement |
|
||||
| Infra | Docker Compose | Simple, reproductible, 3 profils |
|
||||
| LFS | Git LFS | GIFs lourds sans gonfler le repo |
|
||||
|
||||
---
|
||||
|
||||
## 📈 Métriques du Projet
|
||||
|
||||
| Métrique | Valeur |
|
||||
|:---|:---|
|
||||
| Tables DB | 25 |
|
||||
| Endpoints API | 22+ |
|
||||
| Migrations Alembic | 9 |
|
||||
| Modèles Python | 25+ |
|
||||
| Schémas Pydantic | 10+ |
|
||||
| Services | 5 (auth, challenge, health, aggregation, provider) |
|
||||
| Fichiers Android (Kotlin) | 17 |
|
||||
| Tests | 0 ❌ (priorité P0) |
|
||||
| Linting | ruff (configuré) |
|
||||
Reference in New Issue
Block a user