fix(front,db,ci): déploiement web, API même origine, Flutter 3.29, schéma validations

Frontend (prod web):
- Image builder Flutter 3.29.3 (Dockerfile + workflow CI alignés)
- web/index.html: bootstrap Flutter 3.29 (flutter_bootstrap.js), scripts pdf.js conservés
- Dockerfile: rm html avant COPY pour éviter l’index « Welcome to nginx »
- nginx: server_name _ pour Traefik
- env: sur le web, API = Uri.base.origin si pas de API_BASE_URL (évite mixed content http/https)
- auth: message d’erreur réseau avec type/détail si non-Exception
- CGU/PDF: commentaire sans mention Flutter 3.19 obsolète
- pubspec.lock: résolution dépendances Flutter 3.29

Base de données & doc:
- BDD.sql: validations.commentaire, valide_par, FK ON DELETE SET NULL + commentaire
- patch 2026-04-17: valide_par avec ON DELETE SET NULL
- patch 2026-04-18: FK validations en SET NULL sur bases existantes
- seed: statut validation « valide » (enum)
- FK_POLICIES.md: valide_par
- doc workflow: Flutter 3.29.3

Made-with: Cursor
This commit is contained in:
2026-04-22 18:48:17 +02:00
parent fc86181a73
commit 2c746ceff3
15 changed files with 110 additions and 96 deletions
+21 -11
View File
@@ -1,14 +1,24 @@
import 'package:flutter/foundation.dart' show kIsWeb;
class Env {
// Base URL de l'API, surchargeable à la compilation via --dart-define=API_BASE_URL
static const String apiBaseUrl = String.fromEnvironment(
'API_BASE_URL',
defaultValue: 'https://app.ptits-pas.fr',
);
/// Base URL de lAPI (sans `/api/v1`).
///
/// - **Web prod** : par défaut on utilise [Uri.base.origin] (même schéma + hôte que la page),
/// ce qui évite les blocages « mixed content » (ex. page en `http://` vs API en `https://`)
/// et les builds où `--dart-define=API_BASE_URL` ne serait pas passé.
/// - **Web dev** : surcharger avec `--dart-define=API_BASE_URL=http://localhost:3000` (ou lURL du back).
/// - **Mobile** : défaut `https://app.ptits-pas.fr` ou `API_BASE_URL` en `--dart-define`.
static String get apiBaseUrl {
const fromEnv = String.fromEnvironment('API_BASE_URL');
if (fromEnv.isNotEmpty) {
return fromEnv;
}
if (kIsWeb) {
return Uri.base.origin;
}
return 'https://app.ptits-pas.fr';
}
// Construit une URL vers l'API v1 à partir d'un chemin (commençant par '/')
static String apiV1(String path) => '$apiBaseUrl/api/v1$path';
/// Construit une URL vers l'API v1 à partir d'un chemin (commençant par '/')
static String apiV1(String path) => '${apiBaseUrl}/api/v1$path';
}
+4 -1
View File
@@ -69,7 +69,10 @@ class AuthService {
}
} catch (e) {
if (e is Exception) rethrow;
throw Exception('Erreur réseau: impossible de se connecter au serveur');
// Erreurs non-Exception (ex. certains cas côté web) : afficher le détail pour le diagnostic
throw Exception(
'Erreur réseau: impossible de se connecter au serveur (${e.runtimeType}: $e)',
);
}
}
@@ -325,8 +325,8 @@ class _CguPrivacyValidationDialogState extends State<CguPrivacyValidationDialog>
}
}
/// [PdfViewPinch] pour le web / mobile (Flutter 3.19 + pdfx 2.6 : pas de
/// `documentProgress` / `minScale` comme sur les versions plus récentes).
/// [PdfViewPinch] pour le web / mobile avec `pdfx` 2.6 (pas de
/// `documentProgress` / `minScale` dans cette API).
class _PdfPaneWithScrollbar extends StatefulWidget {
const _PdfPaneWithScrollbar({
super.key,