From c8b704216d527eebb39b1bb99a121f41824364a1 Mon Sep 17 00:00:00 2001 From: Luca Date: Sun, 15 Mar 2026 21:24:59 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20redesign=20dark=20futuriste=20(Luca)=20?= =?UTF-8?q?=E2=80=94=20th=C3=A8me=20cyan/volt,=20sidebar=20dark,=20JetBrai?= =?UTF-8?q?ns=20Mono=20+=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 330 ++++++--------- templates/base.html | 628 ++++++++++++++++++++++++++++- templates/client_detail.html | 85 ++-- templates/client_form.html | 54 ++- templates/clients.html | 89 ++-- templates/dashboard.html | 148 ++++--- templates/intervention_detail.html | 229 +++++++---- templates/intervention_form.html | 73 ++-- templates/interventions.html | 130 +++--- templates/vehicule_detail.html | 318 ++++++++++----- templates/vehicule_form.html | 61 +-- templates/vehicules.html | 98 +++-- 12 files changed, 1552 insertions(+), 691 deletions(-) diff --git a/README.md b/README.md index 01ddb3d..c184361 100644 --- a/README.md +++ b/README.md @@ -1,224 +1,154 @@ # 🔧 GarageManager -> Application web de gestion de garage automobile — véhicules, interventions, pièces détachées. +> Application de gestion de garage automobile — suivi véhicules, interventions et pièces. -[![FastAPI](https://img.shields.io/badge/FastAPI-0.109-009688?style=flat&logo=fastapi)](https://fastapi.tiangolo.com) -[![Python](https://img.shields.io/badge/Python-3.12-3776AB?style=flat&logo=python)](https://python.org) -[![Docker](https://img.shields.io/badge/Docker-ready-2496ED?style=flat&logo=docker)](https://docker.com) -[![SQLite](https://img.shields.io/badge/SQLite-léger-003B57?style=flat&logo=sqlite)](https://sqlite.org) - -🌐 **URL de production** : [https://garage.nas.percolouco.com](https://garage.nas.percolouco.com) - ---- - -## 📋 Description - -**GarageManager** est une application web légère permettant de gérer un garage automobile personnel ou professionnel. Elle permet de suivre les véhicules, leurs interventions mécaniques et les pièces utilisées, avec un tableau de bord synthétique. - -Pensée pour être self-hostée, elle tourne dans un conteneur Docker derrière un reverse proxy Traefik. - ---- - -## 🛠️ Stack technique - -| Composant | Technologie | Rôle | -|-----------|-------------|------| -| **Backend** | [FastAPI](https://fastapi.tiangolo.com) 0.109 | API REST + rendu SSR | -| **Base de données** | [SQLite](https://sqlite.org) | Stockage persistant, fichier unique | -| **Templates** | [Jinja2](https://jinja.palletsprojects.com) 3.1 | Rendu HTML côté serveur | -| **CSS** | [Tailwind CSS](https://tailwindcss.com) (CDN) | Interface responsive moderne | -| **Serveur ASGI** | [Uvicorn](https://www.uvicorn.org) | Serveur HTTP haute performance | -| **Conteneur** | [Docker](https://docker.com) + Compose | Déploiement clé en main | -| **Reverse proxy** | [Traefik](https://traefik.io) | HTTPS automatique (Let's Encrypt) | +[![Python](https://img.shields.io/badge/Python-3.11-blue)](https://python.org) +[![FastAPI](https://img.shields.io/badge/FastAPI-latest-009688)](https://fastapi.tiangolo.com) +[![Docker](https://img.shields.io/badge/Docker-compose-2496ED)](https://docs.docker.com/compose/) --- ## ✨ Fonctionnalités -### 🚗 Gestion des véhicules +- **Véhicules** — Enregistrement complet (immatriculation, VIN, kilométrage, marque/modèle/année) +- **Interventions** — Historique par véhicule avec date, kilométrage, technicien, coûts main d'œuvre +- **Pièces** — Suivi par intervention avec référence, marque, prix, quantité et photo optionnelle +- **Clients** — Gestion des propriétaires de véhicules +- **Infos & Notes** — Ajout de textes, URLs et photos sur chaque véhicule +- **Dashboard** — Vue d'ensemble : stats globales, dernières interventions -- Ajout de véhicules avec les informations clés : - - **Immatriculation** (clé unique, mise en majuscules automatiquement) - - **Marque**, **modèle**, **année**, **kilométrage** - - **Numéro VIN** (Vehicle Identification Number) -- **Infos libres** par véhicule : notes texte, liens URL, photos — système extensible -- Recherche par immatriculation, marque, modèle ou VIN -- Compteur d'interventions par véhicule -- Suppression en cascade (interventions + pièces supprimées automatiquement) +## 🎨 Design -### 🔩 Gestion des interventions +Thème sombre futuriste inspiré du projet `location` de Perco : +- Fond noir (`#0a0f1a`) avec dégradés subtils cyan/jaune +- Accents électriques : cyan `#00d4ff` et volt `#facc15` +- Police [Outfit](https://fonts.google.com/specimen/Outfit) + [JetBrains Mono](https://www.jetbrains.com/lp/mono/) pour les références/immatriculations +- Sidebar dark avec navigation intuitive -- Création d'interventions liées à un véhicule -- Champs disponibles : - - **Description** de l'intervention - - **Statut** : `En attente` / `En cours` / `Terminé` - - **Coût main-d'œuvre** - - **Technicien** responsable - - **Notes** internes -- Suivi du coût total (main-d'œuvre + pièces) -- Filtrage par statut +## 🚀 Démarrage rapide -### 🔧 Gestion des pièces détachées +```bash +# Lancer le service +cd /opt/container/garagemanager +docker compose up -d -- Association de pièces à chaque intervention : - - **Nom** de la pièce - - **Référence** constructeur - - **Marque** de la pièce - - **Prix unitaire** et **quantité** - - **Photo** (upload d'image) -- Calcul automatique du coût total par intervention +# Rebuild complet (après modif templates/code) +docker compose build --no-cache && docker compose up -d -### 📊 Tableau de bord +# Logs +docker compose logs -f +``` -- Vue synthétique en temps réel : - - Nombre de véhicules enregistrés - - Interventions par statut (en attente / en cours / terminées) - - Coût total des interventions terminées (pièces + main-d'œuvre) -- 5 dernières interventions avec accès rapide - ---- - -## 📁 Structure du projet +## 🏗️ Architecture ``` garagemanager/ ├── app/ │ ├── __init__.py -│ └── main.py # Application FastAPI (routes, DB, logique) -├── templates/ -│ ├── base.html # Template de base (nav, layout) -│ ├── dashboard.html # Tableau de bord -│ ├── vehicules.html # Liste des véhicules -│ ├── vehicule_form.html # Formulaire ajout/édition véhicule -│ ├── vehicule_detail.html # Détail véhicule + interventions + infos -│ ├── interventions.html # Liste des interventions -│ ├── intervention_form.html # Formulaire ajout/édition intervention -│ └── intervention_detail.html # Détail intervention + pièces -├── data/ # Volume persistant (ignoré par git) -│ └── garage.db # Base SQLite -├── Dockerfile # Image Docker Python 3.12-slim -├── docker-compose.yml # Déploiement avec Traefik -├── requirements.txt # Dépendances Python -└── README.md +│ └── main.py # FastAPI routes + SQLite logic +├── templates/ # Jinja2 templates (thème dark) +│ ├── base.html # Layout sidebar + variables CSS +│ ├── dashboard.html # Stats cards + tableau récent +│ ├── vehicules.html # Liste véhicules +│ ├── vehicule_form.html +│ ├── vehicule_detail.html # Interventions + pièces + infos +│ ├── interventions.html +│ ├── intervention_form.html +│ ├── intervention_detail.html # Détail + gestion pièces +│ ├── clients.html +│ ├── client_form.html +│ └── client_detail.html +├── data/ +│ └── garage.db # Base SQLite (volume Docker) +├── Dockerfile +├── docker-compose.yml +└── requirements.txt ``` +## 🔌 API REST + +FastAPI génère automatiquement la documentation : + +- **Swagger UI** : https://garage.nas.percolouco.com/docs +- **ReDoc** : https://garage.nas.percolouco.com/redoc + +### Endpoints principaux + +| Méthode | Route | Description | +|---------|-------|-------------| +| `GET` | `/` | Dashboard | +| `GET` | `/vehicules` | Liste des véhicules | +| `POST` | `/vehicules/new` | Créer un véhicule | +| `GET` | `/vehicules/{id}` | Détail véhicule | +| `GET` | `/interventions` | Liste des interventions | +| `POST` | `/interventions/new` | Créer une intervention | +| `POST` | `/interventions/{id}/pieces/add` | Ajouter une pièce | + +## 🗃️ Modèle de données (SQLite) + +```sql +-- Clients +CREATE TABLE clients ( + id TEXT PRIMARY KEY, + nom TEXT NOT NULL, + prenom TEXT NOT NULL, + telephone TEXT, + email TEXT, + adresse TEXT, + created_at TEXT +); + +-- Véhicules +CREATE TABLE vehicules ( + id TEXT PRIMARY KEY, + immatriculation TEXT NOT NULL, + marque TEXT NOT NULL, + modele TEXT NOT NULL, + annee INTEGER, + kilometrage INTEGER, + vin TEXT, + client_id TEXT REFERENCES clients(id), + created_at TEXT +); + +-- Interventions +CREATE TABLE interventions ( + id TEXT PRIMARY KEY, + vehicule_id TEXT NOT NULL REFERENCES vehicules(id), + description TEXT NOT NULL, + date_intervention TEXT, + kilometrage_intervention INTEGER, + cout_main_oeuvre REAL DEFAULT 0, + technicien TEXT, + notes TEXT, + created_at TEXT +); + +-- Pièces +CREATE TABLE pieces ( + id TEXT PRIMARY KEY, + intervention_id TEXT NOT NULL REFERENCES interventions(id), + nom TEXT NOT NULL, + reference TEXT, + marque TEXT, + prix REAL DEFAULT 0, + quantite INTEGER DEFAULT 1, + photo TEXT, + created_at TEXT +); +``` + +## ⚙️ Configuration + +| Variable d'env | Défaut | Description | +|----------------|--------|-------------| +| `DB_PATH` | `/data/garage.db` | Chemin vers la base SQLite | + +## 🌐 Accès + +- **Production** : https://garage.nas.percolouco.com +- **Réseau interne** : via Traefik sur le réseau Docker `proxy` + --- -## 🚀 Installation - -### Prérequis - -- Docker & Docker Compose installés -- (Optionnel) Traefik configuré pour HTTPS automatique - -### 1. Cloner le dépôt - -```bash -git clone http://192.168.1.29:3500/perco/garagemanager.git -cd garagemanager -``` - -### 2. Démarrer avec Docker Compose - -**Avec Traefik (production)** : - -```bash -docker compose up -d -``` - -L'application sera accessible via `https://garage.nas.percolouco.com` si Traefik est configuré avec le réseau `proxy`. - -**Sans Traefik (local/dev)** : - -Modifier `docker-compose.yml` pour exposer un port directement : - -```yaml -ports: - - "8000:8000" -``` - -Puis : - -```bash -docker compose up -d -``` - -Accessible sur : `http://localhost:8000` - -### 3. Développement local (sans Docker) - -```bash -# Créer un environnement virtuel -python3 -m venv venv -source venv/bin/activate - -# Installer les dépendances -pip install -r requirements.txt - -# Lancer le serveur avec rechargement automatique -DB_PATH=./data/garage.db uvicorn app.main:app --reload --port 8000 -``` - -Accessible sur : `http://localhost:8000` - ---- - -## 🗄️ Base de données - -La base SQLite est initialisée automatiquement au démarrage. Le schéma comprend 4 tables : - -| Table | Description | -|-------|-------------| -| `vehicules` | Véhicules (immat, marque, modèle, VIN, km) | -| `vehicule_infos` | Infos libres par véhicule (texte/url/image) | -| `interventions` | Interventions mécaniques avec statut et coûts | -| `pieces` | Pièces détachées liées aux interventions | - -Les suppressions en cascade sont gérées par des contraintes SQLite (`ON DELETE CASCADE`). - ---- - -## 🐳 Variables d'environnement - -| Variable | Défaut | Description | -|----------|--------|-------------| -| `DB_PATH` | `/data/garage.db` | Chemin de la base SQLite | -| `UPLOAD_DIR` | `/data/uploads` | Dossier de stockage des photos | - ---- - -## 🔄 Mise à jour - -```bash -# Arrêter le conteneur -docker compose down - -# Récupérer les dernières modifications -git pull - -# Reconstruire l'image et redémarrer -docker compose up -d --build -``` - ---- - -## 📝 Notes - -- Les données sont persistées dans le dossier `./data/` (volume Docker) -- Les photos uploadées sont stockées dans `./data/uploads/` -- Le dossier `data/` est exclu du dépôt git (`.gitignore`) -- L'application ne gère pas d'authentification — à protéger via Traefik middleware si nécessaire - ---- - -## 🏷️ Versions - -| Version | Notes | -|---------|-------| -| v2.1 | Infos libres véhicule (texte/url/image), upload photos pièces | -| v2.0 | Ajout gestion des pièces détachées | -| v1.0 | Gestion véhicules + interventions | - ---- - -*Développé avec ❤️ pour la gestion de garage automobile* +*Développé par l'équipe Perco — Design Luca, Backend intégré FastAPI* diff --git a/templates/base.html b/templates/base.html index f2a8943..f5904d5 100644 --- a/templates/base.html +++ b/templates/base.html @@ -4,31 +4,623 @@ {% block title %}GarageManager{% endblock %} - + + + + + {% block extra_head %}{% endblock %} - -
- -
+ + + + +
{% block content %}{% endblock %} -
+ diff --git a/templates/client_detail.html b/templates/client_detail.html index 42bdc26..2344941 100644 --- a/templates/client_detail.html +++ b/templates/client_detail.html @@ -1,49 +1,74 @@ {% extends "base.html" %} -{% block title %}{{ client.nom }} {{ client.prenom }} - GarageManager{% endblock %} +{% block title %}{{ client.nom }} {{ client.prenom }} — GarageManager{% endblock %} {% block content %} -
- Retour aux clients -
-
-

{{ client.nom }} {{ client.prenom }}

-
- {% if client.telephone %}{{ client.telephone }}{% endif %} - {% if client.email %}{{ client.email }}{% endif %} - {% if client.adresse %}{{ client.adresse }}{% endif %} -
-
-
- Modifier -
- -
+ + Retour aux clients + + +
+
+

{{ client.nom }} {{ client.prenom }}

+
+ {% if client.telephone %} + {{ client.telephone }} + {% endif %} + {% if client.email %} + {{ client.email }} + {% endif %} + {% if client.adresse %} + {{ client.adresse }} + {% endif %}
+
+ + Modifier + +
+ +
+
-
-
-

Véhicules ({{ vehicules|length }})

- + Ajouter un véhicule + + +
+
+ + + Véhicules + {{ vehicules|length }} + + + Ajouter +
+ {% if vehicules %} -
+
{% for v in vehicules %} -
+
- {{ v.immatriculation }} - {{ v.marque }} {{ v.modele }} - {% if v.annee %}({{ v.annee }}){% endif %} - {% if v.kilometrage %}— {{ v.kilometrage }} km{% endif %} + {{ v.immatriculation }} + {{ v.marque }} {{ v.modele }} + {% if v.annee %}({{ v.annee }}){% endif %} + {% if v.kilometrage %}— {{ v.kilometrage }} km{% endif %}
- {{ v.nb_interventions }} intervention(s) - Voir → + {{ v.nb_interventions }} intervention(s) + Voir →
{% endfor %}
{% else %} -
Aucun véhicule enregistré pour ce client.
+
+ +

Aucun véhicule enregistré pour ce client

+ Ajouter un véhicule → +
{% endif %}
+ {% endblock %} diff --git a/templates/client_form.html b/templates/client_form.html index 9771c85..072a1e1 100644 --- a/templates/client_form.html +++ b/templates/client_form.html @@ -1,38 +1,52 @@ {% extends "base.html" %} -{% block title %}{% if client %}Modifier{% else %}Nouveau{% endif %} client - GarageManager{% endblock %} +{% block title %}{% if client %}Modifier{% else %}Nouveau{% endif %} client — GarageManager{% endblock %} {% block content %} -
- Retour -

{% if client %}Modifier le client{% else %}Nouveau client{% endif %}

+ + Retour aux clients + + -
-
-
+ +
+ + +
- - + +
- - + +
+
- - + +
+
- - + +
+
- - + +
-
- - Annuler + +
+ + Annuler
+ {% endblock %} diff --git a/templates/clients.html b/templates/clients.html index fc5bb7f..7ddcd72 100644 --- a/templates/clients.html +++ b/templates/clients.html @@ -1,54 +1,75 @@ {% extends "base.html" %} -{% block title %}Clients - GarageManager{% endblock %} +{% block title %}Clients — GarageManager{% endblock %} {% block content %} -
-

Clients

{{ clients|length }} client(s)

- Nouveau client -
-
-
-
- - - {% if q %}{% endif %} -
+ + + + +
+
+ + + {% if q %} + + {% endif %} +
+
+ +
{% if clients %} - - +
+ - - - - - + + + + + - + {% for c in clients %} - - - - - - + + + + + {% endfor %}
NomTéléphoneEmailVéhiculesActionsNomTéléphoneEmailVéhiculesActions
{{ c.nom }} {{ c.prenom }}{{ c.telephone or '-' }}{{ c.email or '-' }}{{ c.nb_vehicules }} - Voir - Modifier -
- -
+
+ {{ c.nom }} {{ c.prenom }} + {{ c.telephone or '—' }}{{ c.email or '—' }} + {{ c.nb_vehicules }} + +
+ Voir + Modifier +
+ +
+
{% else %} -
-

Aucun client trouvé

- Ajouter le premier → +
+ +

Aucun client trouvé

+ Ajouter le premier →
{% endif %}
+ {% endblock %} diff --git a/templates/dashboard.html b/templates/dashboard.html index 083d6f7..d13413e 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -1,89 +1,119 @@ {% extends "base.html" %} -{% block title %}Dashboard - GarageManager{% endblock %} +{% block title %}Dashboard — GarageManager{% endblock %} {% block content %} -
-

Dashboard

-

Vue d'ensemble de votre garage

+ + -
-
-
-

Véhicules

{{ stats.nb_vehicules }}

-
+ + +
+
+
+
Véhicules
+
+ +
- Voir tous → +
{{ stats.nb_vehicules }}
+ Voir tous →
-
-
-

En attente

{{ stats.nb_en_attente }}

-
+ +
+
+
Interventions
+
+ +
- Voir → +
{{ stats.nb_interventions }}
+ Voir toutes →
-
-
-

En cours

{{ stats.nb_en_cours }}

-
+ +
+
+
Pièces en stock
+
+ +
- Voir → +
{{ stats.nb_pieces_stock }}
+ Pièces référencées
-
-
-

Terminées

{{ stats.nb_termine }}

-
-
- Voir → -
-
-
-

Coût pièces

{{ "%.0f"|format(stats.cout_pieces) }} €

-
-
-
-
-
-

Total dépensé

{{ "%.0f"|format(stats.cout_total) }} €

-
+ +
+
+
Total dépensé
+
+ +
+
{{ "%.0f"|format(stats.cout_total) }} €
+ Toutes interventions
-
-
-

Interventions récentes

- + Nouvelle + + +
+
+ Interventions récentes + + Nouvelle +
+ {% if recent %}
- - +
+ - - - - + + + + + + - + {% for i in recent %} - - - - + + + + + + - {% endfor %}
VéhiculeDescriptionStatutCoût totalVéhiculeDescriptionDateKilométragePiècesTotal
{{ i.immatriculation }}
{{ i.marque }} {{ i.modele }}
{{ i.description[:60] }}{% if i.description|length > 60 %}...{% endif %} - {% if i.statut == 'en_attente' %}En attente - {% elif i.statut == 'en_cours' %}En cours - {% else %}Terminé{% endif %} +
+ {{ i.immatriculation }} +
+ {{ i.marque }} {{ i.modele }} +
+ {{ i.description[:60] }}{% if i.description|length > 60 %}…{% endif %} + {{ i.date_intervention or '—' }}{{ (i.kilometrage_intervention|string + ' km') if i.kilometrage_intervention else '—' }} + {{ i.nb_pieces }} pièce(s) +
+ {{ "%.0f"|format(i.cout_pieces) }} € +
+ {{ "%.0f"|format(i.cout_main_oeuvre + i.cout_pieces) }} € {{ "%.0f"|format(i.cout_main_oeuvre + i.cout_pieces) }} €
{% else %} -
-

Aucune intervention pour l'instant

- Créer la première → +
+ +

Aucune intervention pour l'instant

+ Créer la première →
{% endif %}
+ {% endblock %} diff --git a/templates/intervention_detail.html b/templates/intervention_detail.html index 032ce0c..aec0a6d 100644 --- a/templates/intervention_detail.html +++ b/templates/intervention_detail.html @@ -1,142 +1,203 @@ {% extends "base.html" %} -{% block title %}Intervention #{{ intervention.id }} - GarageManager{% endblock %} +{% block title %}Intervention — GarageManager{% endblock %} {% block content %} -
- Retour au véhicule -
-
-

{{ intervention.description }}

-

{{ intervention.immatriculation }} — {{ intervention.marque }} {{ intervention.modele }}

-

{{ intervention.created_at[:10] }}{% if intervention.technicien %} • {{ intervention.technicien }}{% endif %}

-
-
- {% if intervention.statut == 'en_attente' %}⏳ En attente - {% elif intervention.statut == 'en_cours' %}🔧 En cours - {% else %}✅ Terminé{% endif %} - Modifier -
- -
+ + Retour au véhicule + + +
+
+

{{ intervention.description }}

+

+ {{ intervention.immatriculation }} + — {{ intervention.marque }} {{ intervention.modele }} +

+
+ {% if intervention.date_intervention %} + {{ intervention.date_intervention }} + {% endif %} + {% if intervention.kilometrage_intervention %} + {{ intervention.kilometrage_intervention }} km + {% endif %} + {% if intervention.technicien %} + {{ intervention.technicien }} + {% endif %}
+
+ + Modifier + +
+ +
+
-
-
-

Main d'œuvre

-

{{ "%.2f"|format(intervention.cout_main_oeuvre) }} €

+
+
+
Main d'œuvre
+
{{ "%.2f"|format(intervention.cout_main_oeuvre) }} €
-
-

Pièces

-

{{ "%.2f"|format(intervention.cout_pieces) }} €

+
+
Pièces
+
{{ "%.2f"|format(intervention.cout_pieces) }} €
-
-

Total

-

{{ "%.2f"|format(intervention.cout_main_oeuvre + intervention.cout_pieces) }} €

+
+
Total
+
{{ "%.2f"|format(intervention.cout_main_oeuvre + intervention.cout_pieces) }} €
{% if intervention.notes %} -
-

📋 Notes

-

{{ intervention.notes }}

+
+

Notes

+

{{ intervention.notes }}

{% endif %} - -
-
-

🔩 Pièces utilisées ({{ pieces|length }})

- + +
+
+ + + Pièces utilisées + {{ pieces_utilisees|length }} + +
- -