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.
This commit is contained in:
2026-09-14 02:08:27 +02:00
commit e3f946f7d4
225 changed files with 38168 additions and 0 deletions
Executable
+107
View File
@@ -0,0 +1,107 @@
#!/usr/bin/env bash
# Lance en mode développement le backend (port 8080) et le frontend Angular (port 4200)
# avec la base SQLite réelle. À utiliser hors Docker, pour le développement local.
#
# Usage : ./run-dev.sh
# Arrêt : Ctrl+C (les deux processus sont arrêtés ensemble).
set -uo pipefail
RACINE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# --- Backend (.NET 8) -------------------------------------------------------
export PATH="$HOME/.dotnet:$HOME/.dotnet/tools:$PATH"
export DOTNET_ROOT="$HOME/.dotnet"
# Base réelle, chemin ABSOLU pour éviter deux bases selon le dossier de lancement.
export ConnectionStrings__Default="Data Source=$RACINE/backend/TrajetKmTracker.Api/trajets.db"
export ASPNETCORE_ENVIRONMENT=Development
# Clé OpenRouteService : lue depuis .env (ORS_API_KEY) et injectée sous le nom attendu
# par la configuration .NET (ORS__ApiKey). Sans clé valide, le backend calcule les
# distances à vol d'oiseau (fallback Haversine) au lieu de la distance routière réelle.
if [[ -z "${ORS__ApiKey:-}" && -f "$RACINE/.env" ]]; then
ORS_KEY_FROM_ENV="$(grep -E '^ORS_API_KEY=' "$RACINE/.env" | head -n1 | cut -d= -f2- || true)"
if [[ -n "$ORS_KEY_FROM_ENV" ]]; then
export ORS__ApiKey="$ORS_KEY_FROM_ENV"
echo "→ Clé ORS chargée depuis .env (calcul de distance routière activé)."
else
echo "⚠ Aucune clé ORS dans .env : distances calculées à vol d'oiseau."
fi
fi
echo "→ Démarrage du backend sur http://localhost:8080 (base : $RACINE/backend/TrajetKmTracker.Api/trajets.db)"
dotnet run --project "$RACINE/backend/TrajetKmTracker.Api" --urls http://localhost:8080 &
PID_BACK=$!
# --- Frontend (Angular via nvm/Node 22) -------------------------------------
export NVM_DIR="$HOME/.nvm"
# shellcheck source=/dev/null
. "$NVM_DIR/nvm.sh"
nvm use 22 >/dev/null
# Vide le cache de compilation Angular pour garantir un bundle à jour, notamment
# le polyfill zone.js (sans lui, la vue ne se rafraîchit pas sur les réponses HTTP :
# `window.Zone` doit être défini au runtime). Un cache périmé peut resservir un
# ancien polyfills sans zone.js.
echo "→ Nettoyage du cache Angular (.angular/cache)"
rm -rf "$RACINE/frontend/.angular/cache"
echo "→ Démarrage du frontend sur http://localhost:4200 (première compilation : patiente…)"
( cd "$RACINE/frontend" && npm start ) &
PID_FRONT=$!
# --- Arrêt propre des deux processus ----------------------------------------
cleanup() {
echo ""
echo "→ Arrêt…"
kill "$PID_BACK" "$PID_FRONT" 2>/dev/null || true
pkill -f "TrajetKmTracker.Api" 2>/dev/null || true
}
trap cleanup EXIT INT TERM
# --- Attente active : ng serve prêt à répondre en HTTP 200 ------------------
# La première compilation (surtout après vidage du cache) peut prendre 30–60 s.
# Tant que ng serve n'a pas fini, le port répond « connexion refusée » (HTTP 000)
# et le navigateur chargerait une page incomplète (zone.js absent → window.Zone
# undefined). On ne montre l'invitation qu'une fois le serveur réellement prêt.
attendre_frontend() {
local url="http://localhost:4200/"
local max=120 # secondes
local t=0
printf "→ Compilation du frontend"
while [ "$t" -lt "$max" ]; do
# Le process ng serve est-il toujours vivant ?
if ! kill -0 "$PID_FRONT" 2>/dev/null; then
echo ""
echo "✗ Le frontend s'est arrêté avant d'être prêt (voir les logs ci-dessus)."
return 1
fi
local code
code=$(curl -s -o /dev/null -w "%{http_code}" "$url" 2>/dev/null || echo 000)
if [ "$code" = "200" ]; then
echo " prêt."
return 0
fi
printf "."
sleep 2
t=$((t + 2))
done
echo ""
echo "✗ Le frontend n'a pas répondu 200 au bout de ${max}s. Vérifie les logs ng serve."
return 1
}
if attendre_frontend; then
echo ""
echo "======================================================================"
echo " Application prête."
echo " Backend : http://localhost:8080/api"
echo " Frontend : http://localhost:4200 ← ouvre cette URL maintenant"
echo ""
echo " Au premier chargement, fais Ctrl+Shift+R pour vider le cache navigateur."
echo " Vérif : dans la console DevTools, 'window.Zone' doit renvoyer un objet."
echo "======================================================================"
echo ""
fi
wait