feat(frontend): #50 — validation CGU et politique de confidentialité
- Modale de validation avec chargement des PDF distants, PdfViewPinch et barre de progression latérale (repli PdfView sous Windows). - Service documents légaux actifs, correction des URLs média, intégration au formulaire de présentation. - Documentation juridique et réorganisation (archive, index, tickets). Made-with: Cursor
This commit is contained in:
@@ -8,6 +8,39 @@ import 'package:p_tits_pas/models/dossier_unifie.dart';
|
||||
import 'package:p_tits_pas/services/api/api_config.dart';
|
||||
import 'package:p_tits_pas/services/api/tokenService.dart';
|
||||
|
||||
class DocumentActifInfo {
|
||||
final String id;
|
||||
final String type;
|
||||
final int version;
|
||||
final String url;
|
||||
|
||||
const DocumentActifInfo({
|
||||
required this.id,
|
||||
required this.type,
|
||||
required this.version,
|
||||
required this.url,
|
||||
});
|
||||
|
||||
factory DocumentActifInfo.fromJson(Map<String, dynamic> json) {
|
||||
return DocumentActifInfo(
|
||||
id: (json['id'] ?? '').toString(),
|
||||
type: (json['type'] ?? '').toString(),
|
||||
version: int.tryParse((json['version'] ?? '').toString()) ?? 0,
|
||||
url: (json['url'] ?? '').toString(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class DocumentsActifsInfo {
|
||||
final DocumentActifInfo cgu;
|
||||
final DocumentActifInfo privacy;
|
||||
|
||||
const DocumentsActifsInfo({
|
||||
required this.cgu,
|
||||
required this.privacy,
|
||||
});
|
||||
}
|
||||
|
||||
class UserService {
|
||||
static Future<Map<String, String>> _headers() async {
|
||||
final token = await TokenService.getToken();
|
||||
@@ -34,6 +67,46 @@ class UserService {
|
||||
return _toStr(err) ?? 'Erreur inconnue';
|
||||
}
|
||||
|
||||
/// Documents légaux actifs (CGU + privacy). GET /documents-legaux/actifs.
|
||||
static Future<DocumentsActifsInfo> getDocumentsLegauxActifs() async {
|
||||
final response = await http.get(
|
||||
Uri.parse('${ApiConfig.baseUrl}/documents-legaux/actifs'),
|
||||
headers: ApiConfig.headers,
|
||||
);
|
||||
if (response.statusCode != 200) {
|
||||
try {
|
||||
final err = jsonDecode(response.body);
|
||||
throw Exception(_errMessage(err is Map ? err['message'] : err));
|
||||
} catch (e) {
|
||||
if (e is Exception) rethrow;
|
||||
throw Exception(
|
||||
'Erreur chargement documents légaux (${response.statusCode})',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
final decoded = jsonDecode(response.body);
|
||||
if (decoded is! Map<String, dynamic>) {
|
||||
throw const FormatException('Réponse invalide');
|
||||
}
|
||||
final cgu = decoded['cgu'];
|
||||
final privacy = decoded['privacy'];
|
||||
if (cgu is! Map || privacy is! Map) {
|
||||
throw const FormatException('Documents actifs manquants');
|
||||
}
|
||||
return DocumentsActifsInfo(
|
||||
cgu: DocumentActifInfo.fromJson(Map<String, dynamic>.from(cgu)),
|
||||
privacy: DocumentActifInfo.fromJson(Map<String, dynamic>.from(privacy)),
|
||||
);
|
||||
} catch (e) {
|
||||
if (e is FormatException) rethrow;
|
||||
throw Exception(
|
||||
'Réponse invalide (documents légaux): ${e is Exception ? e.toString() : "format inattendu"}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Utilisateurs en attente de validation (GET /users/pending). Ticket #107.
|
||||
static Future<List<AppUser>> getPendingUsers({String? role}) async {
|
||||
final query = role != null ? '?role=$role' : '';
|
||||
|
||||
Reference in New Issue
Block a user