feat(am): inscription photo (picker, bytes web, photo_filename) (#120)
- ProfessionalInfoFormScreen : ImagePicker par défaut, MemoryImage, consentement si photo réelle - AmRegistrationData : photoBytes + photoFilename ; récap étape 4 - registerAM : base64 + filename, erreurs réseau/JSON comme parents - docs: 23_LISTE-TICKETS — issue #120 Made-with: Cursor
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../models/user.dart';
|
||||
@@ -13,6 +15,13 @@ import '../utils/nir_utils.dart';
|
||||
class AuthService {
|
||||
static const String _currentUserKey = 'current_user';
|
||||
|
||||
static String? _basenameFromPath(String path) {
|
||||
final s = path.replaceAll(r'\', '/');
|
||||
final i = s.lastIndexOf('/');
|
||||
final name = i >= 0 ? s.substring(i + 1) : s;
|
||||
return name.isEmpty ? null : name;
|
||||
}
|
||||
|
||||
/// Connexion de l'utilisateur
|
||||
/// Retourne l'utilisateur connecté avec le flag changement_mdp_obligatoire
|
||||
static Future<AppUser> login(String email, String password) async {
|
||||
@@ -142,17 +151,29 @@ class AuthService {
|
||||
/// En cas de succès (201), aucune donnée utilisateur retournée ; rediriger vers login.
|
||||
static Future<void> registerAM(AmRegistrationData data) async {
|
||||
String? photoBase64;
|
||||
if (data.photoPath != null && data.photoPath!.isNotEmpty && !data.photoPath!.startsWith('assets/')) {
|
||||
try {
|
||||
final file = File(data.photoPath!);
|
||||
if (await file.exists()) {
|
||||
final bytes = await file.readAsBytes();
|
||||
photoBase64 = 'data:image/jpeg;base64,${base64Encode(bytes)}';
|
||||
}
|
||||
} catch (_) {}
|
||||
String? photoFilename;
|
||||
|
||||
if (data.photoBytes != null && data.photoBytes!.isNotEmpty) {
|
||||
photoBase64 = 'data:image/jpeg;base64,${base64Encode(data.photoBytes!)}';
|
||||
final fn = (data.photoFilename ?? '').trim();
|
||||
photoFilename = fn.isNotEmpty ? fn : 'photo_am.jpg';
|
||||
} else if (data.photoPath != null &&
|
||||
data.photoPath!.isNotEmpty &&
|
||||
!data.photoPath!.startsWith('assets/')) {
|
||||
if (!kIsWeb) {
|
||||
try {
|
||||
final file = File(data.photoPath!);
|
||||
if (await file.exists()) {
|
||||
final bytes = await file.readAsBytes();
|
||||
photoBase64 = 'data:image/jpeg;base64,${base64Encode(bytes)}';
|
||||
photoFilename =
|
||||
_basenameFromPath(data.photoPath!) ?? 'photo_am.jpg';
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
|
||||
final body = {
|
||||
final body = <String, dynamic>{
|
||||
'email': data.email,
|
||||
'prenom': data.firstName,
|
||||
'nom': data.lastName,
|
||||
@@ -161,6 +182,7 @@ class AuthService {
|
||||
'code_postal': data.postalCode.isNotEmpty ? data.postalCode : null,
|
||||
'ville': data.city.isNotEmpty ? data.city : null,
|
||||
if (photoBase64 != null) 'photo_base64': photoBase64,
|
||||
if (photoBase64 != null) 'photo_filename': photoFilename ?? 'photo_am.jpg',
|
||||
'consentement_photo': data.photoConsent,
|
||||
'date_naissance': data.dateOfBirth != null
|
||||
? '${data.dateOfBirth!.year}-${data.dateOfBirth!.month.toString().padLeft(2, '0')}-${data.dateOfBirth!.day.toString().padLeft(2, '0')}'
|
||||
@@ -175,11 +197,29 @@ class AuthService {
|
||||
'acceptation_privacy': data.cguAccepted,
|
||||
};
|
||||
|
||||
final response = await http.post(
|
||||
Uri.parse('${ApiConfig.baseUrl}${ApiConfig.registerAM}'),
|
||||
headers: ApiConfig.headers,
|
||||
body: jsonEncode(body),
|
||||
);
|
||||
final String encodedBody;
|
||||
try {
|
||||
encodedBody = jsonEncode(body);
|
||||
} catch (_) {
|
||||
throw Exception(
|
||||
'Impossible de préparer l’envoi (données trop volumineuses ou invalides). '
|
||||
'Réessayez avec une photo plus légère.',
|
||||
);
|
||||
}
|
||||
|
||||
late final http.Response response;
|
||||
try {
|
||||
response = await http.post(
|
||||
Uri.parse('${ApiConfig.baseUrl}${ApiConfig.registerAM}'),
|
||||
headers: ApiConfig.headers,
|
||||
body: encodedBody,
|
||||
);
|
||||
} on http.ClientException {
|
||||
throw Exception(
|
||||
'Connexion à ${ApiConfig.baseUrl} impossible. Vérifiez votre réseau, '
|
||||
'un pare-feu ou un bloqueur, puis réessayez.',
|
||||
);
|
||||
}
|
||||
|
||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user