feat(#112): aligner reprise front sur dossier complet GET/PATCH
Préremplit parents, enfants, motivation et fiche AM depuis reprise-dossier et envoie le body PATCH complet (co-parent, enfants par id, champs pro AM). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import '../models/am_registration_data.dart';
|
||||
import '../models/user_registration_data.dart';
|
||||
import 'nir_utils.dart';
|
||||
import 'parent_registration_payload.dart';
|
||||
|
||||
/// Body PATCH /auth/reprise-resoumettre. Ticket #112.
|
||||
class ReprisePayload {
|
||||
ReprisePayload._();
|
||||
|
||||
static Map<String, dynamic> parentPatch(
|
||||
UserRegistrationData data,
|
||||
String token,
|
||||
) {
|
||||
final base = ParentRegistrationPayload.toJson(data);
|
||||
base.remove('email');
|
||||
base.remove('acceptation_cgu');
|
||||
base.remove('acceptation_privacy');
|
||||
base['token'] = token.trim();
|
||||
|
||||
final enfants = data.children.asMap().entries.map((e) {
|
||||
final childMap = ParentRegistrationPayload.childToRepriseJson(
|
||||
e.value,
|
||||
e.key,
|
||||
data.parent1.lastName.trim(),
|
||||
);
|
||||
return childMap;
|
||||
}).toList();
|
||||
base['enfants'] = enfants;
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> amPatch(
|
||||
AmRegistrationData data,
|
||||
String token, {
|
||||
String? existingPhotoUrl,
|
||||
}) async {
|
||||
final body = <String, dynamic>{'token': token.trim()};
|
||||
|
||||
_put(body, 'prenom', data.firstName.trim());
|
||||
_put(body, 'nom', data.lastName.trim());
|
||||
_put(body, 'telephone', data.phone.trim());
|
||||
_put(body, 'adresse', data.streetAddress.trim());
|
||||
_put(body, 'code_postal', data.postalCode.trim());
|
||||
_put(body, 'ville', data.city.trim());
|
||||
|
||||
body['consentement_photo'] = data.photoConsent;
|
||||
|
||||
if (data.dateOfBirth != null) {
|
||||
final d = data.dateOfBirth!;
|
||||
body['date_naissance'] =
|
||||
'${d.year}-${d.month.toString().padLeft(2, '0')}-${d.day.toString().padLeft(2, '0')}';
|
||||
}
|
||||
_put(body, 'lieu_naissance_ville', data.birthCity.trim());
|
||||
_put(body, 'lieu_naissance_pays', data.birthCountry.trim());
|
||||
_put(body, 'numero_agrement', data.agrementNumber.trim());
|
||||
if (data.nir.trim().isNotEmpty) {
|
||||
body['nir'] = normalizeNir(data.nir);
|
||||
}
|
||||
if (data.agreementDate != null) {
|
||||
final d = data.agreementDate!;
|
||||
body['date_agrement'] =
|
||||
'${d.year}-${d.month.toString().padLeft(2, '0')}-${d.day.toString().padLeft(2, '0')}';
|
||||
}
|
||||
if (data.capacity != null) {
|
||||
body['capacite_accueil'] = data.capacity;
|
||||
}
|
||||
if (data.placesAvailable != null) {
|
||||
body['places_disponibles'] = data.placesAvailable;
|
||||
}
|
||||
if (data.presentationText.trim().isNotEmpty) {
|
||||
body['biographie'] = data.presentationText.trim();
|
||||
}
|
||||
|
||||
final photo = await _amPhotoPayload(data, existingPhotoUrl);
|
||||
if (photo != null) {
|
||||
body.addAll(photo);
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
static Future<Map<String, String>?> _amPhotoPayload(
|
||||
AmRegistrationData data,
|
||||
String? existingPhotoUrl,
|
||||
) async {
|
||||
if (data.photoBytes != null && data.photoBytes!.isNotEmpty) {
|
||||
final mime = _imageMimeForBytes(data.photoBytes!);
|
||||
final fn = (data.photoFilename ?? '').trim();
|
||||
return {
|
||||
'photo_base64':
|
||||
'data:$mime;base64,${base64Encode(data.photoBytes!)}',
|
||||
'photo_filename': fn.isNotEmpty ? fn : 'photo_am.jpg',
|
||||
};
|
||||
}
|
||||
|
||||
if (!kIsWeb &&
|
||||
data.photoPath != null &&
|
||||
data.photoPath!.isNotEmpty &&
|
||||
!data.photoPath!.startsWith('assets/') &&
|
||||
!data.photoPath!.startsWith('http')) {
|
||||
try {
|
||||
final file = File(data.photoPath!);
|
||||
if (await file.exists()) {
|
||||
final bytes = await file.readAsBytes();
|
||||
final mime = _imageMimeForBytes(bytes);
|
||||
return {
|
||||
'photo_base64': 'data:$mime;base64,${base64Encode(bytes)}',
|
||||
'photo_filename':
|
||||
_basenameFromPath(data.photoPath!) ?? 'photo_am.jpg',
|
||||
};
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
final url = (existingPhotoUrl ?? data.repriseExistingPhotoUrl ?? '').trim();
|
||||
if (url.isNotEmpty) {
|
||||
return {'photo_url': url};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static String _imageMimeForBytes(Uint8List bytes) {
|
||||
if (bytes.length >= 2 && bytes[0] == 0xFF && bytes[1] == 0xD8) {
|
||||
return 'image/jpeg';
|
||||
}
|
||||
if (bytes.length >= 8 &&
|
||||
bytes[0] == 0x89 &&
|
||||
bytes[1] == 0x50 &&
|
||||
bytes[2] == 0x4E &&
|
||||
bytes[3] == 0x47) {
|
||||
return 'image/png';
|
||||
}
|
||||
return 'image/jpeg';
|
||||
}
|
||||
|
||||
static String? _basenameFromPath(String path) {
|
||||
final parts = path.replaceAll('\\', '/').split('/');
|
||||
return parts.isEmpty ? null : parts.last;
|
||||
}
|
||||
|
||||
static void _put(Map<String, dynamic> m, String key, String value) {
|
||||
if (value.isNotEmpty) m[key] = value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user