Commit Graph
17 Commits
Author SHA1 Message Date
MadJax d9618d140b Mois vide : suppression des alertes rouges et du message vide en double
Un mois sans trajet est un cas normal, pas une erreur :

- Panneau totaux : plus d'alerte « Impossible de charger les totaux ». Un
  jour/mois sans trajet affiche simplement des totaux à 0,00 km. Signal erreur
  supprimé.
- Consultation : plus d'alerte « Impossible de charger les trajets du mois ».
  Signal erreur et variable resumeEnErreur supprimés ; un échec de résumé
  affiche une liste vide (les vraies indisponibilités serveur restent signalées
  par l'intercepteur global).
- Message vide unique : « Aucun trajet pour ce mois » n'est plus affiché en
  double (retiré de la liste, conservé côté consultation avec garde de
  chargement).

Builds dev et prod OK.
2026-09-15 21:18:13 +02:00
MadJax 926ef32166 Consultation : nav jour remontée au-dessus des totaux
Les totaux affichés sont relatifs au jour ciblé sur la carte. La bande
« ‹ Jour préc. / date / Jour suiv. › » est déplacée juste sous le sélecteur de
mois, au-dessus du panneau des totaux, afin que la date pilote visuellement les
totaux et la carte qui suivent.

Build prod OK.
2026-09-15 21:08:51 +02:00
MadJax 0c9f280b7f Carte : navigation jour limitée aux jours ayant des trajets
Les boutons « Jour préc. » / « Jour suiv. » de la carte ne s'arrêtent plus sur
tous les jours du mois mais uniquement sur les jours comportant des trajets.

Exception : dans le mois en cours, le jour courant reste navigable même sans
trajet (pour pouvoir y ajouter un trajet).

- joursNavigables() : jours du mois avec trajets (+ aujourd'hui si mois courant),
  triés. La date affichée n'a pas besoin d'en faire partie.
- jourNavigableAdjacent() : jour navigable strictement avant/après la date
  affichée ; boutons désactivés s'il n'y en a pas.
- À la sélection d'un mois passé, la carte se recale sur le dernier jour ayant
  des trajets si le jour par défaut tombe sur une journée vide.

Builds dev et prod OK.
2026-09-15 21:05:46 +02:00
MadJax 3342fd8ec2 Liste : journées repliables + libellé « Choisir un mois »
- Sélecteur temporel : libellé « 📅 Choisir une date » → « 📅 Choisir un mois ».

- Liste mensuelle : chaque journée est désormais repliable (en-tête cliquable
  avec chevron, date et nombre de trajets). Par défaut toutes les journées sont
  repliées ; au changement de mois, seule la dernière journée comportant des
  trajets est dépliée. Les mises à jour au sein du même mois (ajout, suppression,
  réordonnancement) conservent l'état d'ouverture courant.

- La date, désormais portée par l'en-tête du groupe, est retirée de chaque ligne
  de trajet (suppression du doublon) ; le commentaire occupe seul sa ligne.

Builds dev et prod OK.
2026-09-15 21:01:06 +02:00
MadJax 48d75b8e06 Consultation par mois : liste mensuelle groupée par jour, carte par jour
Refonte de la navigation temporelle suite au retour d'usage :

- Sélecteur temporel limité à année/mois (suppression du segment jour).
  Nouvel Output moisSelectionne: {annee, mois} en remplacement de
  dateSelectionnee (jour ISO). Surbrillance des mois avec données conservée.

- Consultation : deux états distincts. Le signal mois pilote le chargement
  de la liste (tous les trajets du mois, triés par date), le signal date
  pilote la carte (trajets du jour) et la date par défaut à l'ajout/insertion.
  Bande « ‹ Jour préc. / date / Jour suiv. › » au-dessus de la carte, bornée
  au mois sélectionné. La navigation jour ne recharge que la carte.

- Liste : trajets du mois groupés par journée (en-tête de date). Un
  cdkDropList indépendant par jour (listes non connectées) : le
  réordonnancement par glisser-déposer est limité à chaque journée, avec
  recalcul des positions internes et rétablissement en cas d'échec.

Builds dev et prod OK. Backend inchangé (API résumé mensuel/réordonner
déjà en place).
2026-09-15 20:53:25 +02:00
MadJax 40094a4fb1 Register : retire le lien « Déjà un compte ? Se connecter »
La page d'inscription n'est atteinte que lorsqu'aucun compte n'existe (application
mono-utilisateur) : le lien vers la connexion n'a pas de sens. Import RouterLink
devenu inutile retiré du composant.
2026-09-15 20:22:11 +02:00
MadJax 5c80102dca Auth : rejeter les jetons dont le compte n'existe plus (validation de session)
Corrige un contournement : après réinitialisation de la base (même JWT_SECRET_KEY),
un jeton restait cryptographiquement valide et donnait accès alors que le compte
n'existait plus, permettant d'atteindre l'onboarding sans s'inscrire.

- Backend : JwtBearer.OnTokenValidated vérifie désormais l'existence du compte
  référencé par le claim sub (lu sous 'sub' ou NameIdentifier selon le remapping)
  et rejette le jeton (401) si le compte est introuvable.
- Backend : nouvel endpoint protégé GET /api/auth/moi (SessionController) renvoyant
  200 si la session est réellement valide, 401 sinon.
- Frontend : authGuard valide la session côté serveur (GET /auth/moi) au lieu de se
  fier au seul jeton local ; sur échec, redirection vers /login (jeton purgé par
  l'intercepteur sur 401). AuthService.validerSession() ajouté.

Tests backend : 54/54 au vert.
2026-09-15 20:13:23 +02:00
MadJax f3465e04d2 Corrections UX : première connexion, carte Leaflet en prod, mise en page
- Onboarding : redirection automatique vers /register lorsqu'aucun compte n'existe
  (première utilisation), au lieu d'afficher la page de connexion.
- Carte Leaflet en production : import normalisé (Leaflet est CommonJS, l'API pouvait
  se retrouver sous .default en build prod -> échec d'initialisation). Nettoyage du
  marqueur _leaflet_id du conteneur pour que « Réessayer » fonctionne après un échec.
  Logs d'erreur explicites en cas d'échec d'import/init.
- Mise en page : layout applicatif en flex pleine hauteur (nav de hauteur naturelle,
  <main> occupe le reste et défile si besoin) sans étirer les vues courtes. La vue
  Trajets occupe l'espace restant (height:100%) sans scrollbar de page : seule la
  liste défile. Reset global (body margin 0, box-sizing border-box) supprimant la
  scrollbar de page parasite.
- Centrage uniforme des pages : ajout de margin:0 auto aux vues profil, véhicules,
  barème, résumé mensuel/annuel et montants réglés (comme trajets et carnet).

Builds backend (solution) et frontend (production) OK.
2026-09-15 19:53:16 +02:00
MadJax 8d3528df37 Ajoute backend/.dockerignore (exclut bin/obj, bases .db et projet de tests du contexte)
Évite d'embarquer les artefacts .NET (~220 Mo) et les bases SQLite locales dans le
contexte de build de l'image backend. Build de l'image API validé sans le projet de tests.
2026-09-15 15:19:29 +02:00
MadJax c7819617d5 .env.example : aligner AUTH_FRONTEND_BASE_URL sur le port hôte 2202
Cohérence avec le changement de port publié du frontend (2202). En production,
cette variable doit valoir l'URL publique HTTPS servie par Caddy.
2026-09-15 15:09:31 +02:00
MadJax c48251187c Docker : publier le frontend sur le port hôte 2202 (au lieu de 8080)
Évite un conflit avec une instance existante sur 8080. Seul le port HÔTE change
(2202:80) ; les ports internes des conteneurs (backend 8080) sont inchangés, donc
le proxy interne nginx -> backend n'est pas affecté. Auth__FrontendBaseUrl par défaut
et Caddyfile.example alignés sur 2202.
2026-09-15 15:04:51 +02:00
MadJax e9178e3c20 Caddyfile.example : Caddy sur machine séparée (IP Docker + sécurité réseau)
Configuration reverse_proxy vers l'IP de la machine Docker (port 8080 publié par le
compose), en-têtes X-Forwarded-*, sonde /health, et recommandations de sécurité
(restreindre le port 8080 à l'IP de Caddy / réseau privé) pour éviter un accès HTTP
direct contournant le TLS.
2026-09-15 12:36:50 +02:00
MadJax a11f3c4a10 Déploiement derrière reverse-proxy TLS (Caddy)
- Retire app.UseHttpsRedirection() : le conteneur écoute en HTTP, la terminaison
  TLS est assurée par le reverse-proxy (Caddy) placé devant. Évite les redirections
  parasites derrière le proxy.
- Ajoute Caddyfile.example (Caddy devant le compose existant : TLS auto + reverse_proxy
  vers le frontend nginx qui sert l'app et proxifie /api).
- .env.example : précise AUTH_FRONTEND_BASE_URL = URL publique HTTPS en production
  (liens de réinitialisation de mot de passe).
2026-09-15 12:34:49 +02:00
MadJax 09c24d5f59 UX consultation, trajets aller/retour et rafraîchissement des totaux
- Totaux : rafraîchissement immédiat du panneau (jour/mois/année + montant
  prévisionnel) après création/modification/suppression/réordonnancement d'un
  trajet, sans changer de jour (ViewChild + méthode publique rafraichir()).
- Trajets Aller/Retour : case à cocher au formulaire ; la distance comptée est
  doublée (distance simple stockée + booléen AllerRetour, distance effective
  utilisée dans tous les agrégats : totaux, résumés, barème, régularisation, PDF).
  Migration TrajetAllerRetour. Badge « A/R » dans une colonne dédiée en début de
  ligne pour garder date/adresses alignées.
- Mise en page de la page Trajets : vue à hauteur fixe où seule la liste défile ;
  colonne gauche figée (sélecteur de date + navigation, totaux, carte) et bande
  fixe (véhicule + bouton d'ajout) au-dessus de la liste. Layout applicatif global
  en pleine hauteur (app.component).
- run-dev.sh : chargement de la clé JWT depuis .env (ou secret de dev aléatoire) et
  Auth__FrontendBaseUrl sur le frontend dev ; rappel du lien de reset journalisé.

Build backend (solution) et frontend (production) OK.
2026-09-15 12:33:10 +02:00
MadJax dd36bbc425 Ajout de l'authentification (compte unique, JWT, reset par email)
Application mono-utilisateur : inscription unique, connexion par JWT (12 h),
protection de toutes les routes de données, réinitialisation de mot de passe
par email avec repli de journalisation, onboarding réorganisé en deux étapes
(inscription → connexion → profil + véhicule).

Backend (SchotzIadKmTracker.Api) :
- Entités Compte (singleton) et ResetPasswordToken + migration AjoutAuthentification.
- Hachage PasswordHasher, JwtService (HS256, durée configurable), IEmailService
  (MailKit + repli LoggingEmailService selon Smtp:Host).
- AuthService (register 409 si compte existant, login 401 générique, forgot-password
  non-divulgation, reset à usage unique + expiration), AuthController (5 endpoints
  publics), DTOs + validateurs FluentValidation.
- Sécurité pipeline : JwtBearer + filtre d'autorisation global, UseAuthentication
  avant UseAuthorization ; /health et /api/auth/* publics.

Frontend (schotziad-km-tracker, zoneless + signals) :
- AuthService (localStorage), authInterceptor (Bearer + purge/redirection 401),
  authGuard, écrans Login/Register/ForgotPassword/ResetPassword, routes publiques
  et protection [authGuard, profilConfigureGuard].

Configuration : .env.example et docker-compose.yml (JWT__SecretKey, durées, Smtp__*).

Tests : 54 tests backend (propriétés FsCheck P1–P14, exemples, intégration
WebApplicationFactory) + tests frontend (AuthService, authGuard, authInterceptor,
ResetPasswordComponent). Suite complète au vert.

Spec : .kiro/specs/authentification (requirements, design, tasks).
2026-09-14 09:07:08 +02:00
MadJax 0e6a97ca61 Renommage : TrajetKmTracker -> SchotzIadKmTracker (backend, specs, frontend)
- Backend : projets, solution, namespaces et références
  TrajetKmTracker.Api/.Tests -> SchotzIadKmTracker.Api/.Tests
  (dossiers, .csproj, .sln, .http, namespaces C#). GUID UserSecretsId préservé.
- Specs : dossier .kiro/specs/trajet-km-tracker -> schotziad-km-tracker
  et mise à jour des références internes (chemins, tags de propriétés).
- Frontend : projet Angular trajet-km-tracker -> schotziad-km-tracker
  (package.json, angular.json, chemin dist, Dockerfile), titre applicatif
  'SchotzIAD KM Tracker'.
- Docker et scripts (backend/Dockerfile, frontend/Dockerfile, run-dev.sh) mis à jour.
- Suppression du fichier résiduel package.json.bak.

Backend (solution) et frontend (build production) compilent sans erreur.
2026-09-14 07:50:26 +02:00
MadJax e3f946f7d4 SchotzIAD KM Tracker : suivi des trajets kilométriques (Angular + .NET 8)
Application complète de saisie et de suivi des trajets kilométriques avec
calcul de distance routière (OpenRouteService), barème kilométrique, résumés
et régularisation annuelle.

Backend (ASP.NET Core .NET 8, EF Core, SQLite) :
- Trajets (CRUD, réordonnancement, insertion), calcul de distance ORS avec
  fallback Haversine, géométrie d'itinéraire stockée par trajet, recalcul en masse.
- Profil, véhicules (avec dénomination), carnet d'adresses nommées, cache d'adresses.
- Barème kilométrique : tranches multiples par puissance fiscale, borne max
  exclusive avec 'illimité' (KmMax nullable), coefficient à 3 décimales,
  recopie du dernier barème connu.
- Résumés mensuel/annuel, montants réglés, régularisation, export PDF.

Frontend (Angular 22, zoneless + signals) :
- Consultation par jour, navigation temporelle synchronisée, carte Leaflet,
  formulaire de trajet (adresses nommées, domicile, autocomplétion BAN).
- Détection de changement zoneless (indépendante de zone.js).

Hébergement : Docker Compose (nginx + backend), scripts run-dev.sh / run-docker.sh.
2026-09-14 02:08:27 +02:00