feat(#112): lien login « J'ai un numéro de dossier » + reprise-identify

Modale numéro + e-mail, obtention du token puis redirection vers /reprise.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-16 17:01:18 +02:00
co-authored by Cursor
parent 9b7231f1da
commit c438009286
4 changed files with 243 additions and 0 deletions
+45
View File
@@ -290,6 +290,51 @@ class AuthService {
return RepriseDossier.fromJson(decoded);
}
/// Modale login : numéro + e-mail → token reprise. POST /auth/reprise-identify. #112.
static Future<String> identifyReprise({
required String numeroDossier,
required String email,
}) async {
final num = numeroDossier.trim();
final mail = normalizeEmailText(email);
if (num.isEmpty || mail.isEmpty) {
throw Exception('Numéro de dossier et e-mail requis.');
}
late final http.Response response;
try {
response = await http.post(
Uri.parse('${ApiConfig.baseUrl}${ApiConfig.repriseIdentify}'),
headers: ApiConfig.headers,
body: jsonEncode({
'numero_dossier': num,
'email': mail,
}),
);
} on http.ClientException {
throw Exception(
'Connexion à ${ApiConfig.baseUrl} impossible. Vérifiez votre réseau puis réessayez.',
);
}
if (response.statusCode == 404) {
throw Exception(
'Aucun dossier en reprise trouvé pour ce numéro et cet e-mail.',
);
}
if (response.statusCode != 200 && response.statusCode != 201) {
final decoded = _tryDecodeJsonMap(response.body);
throw Exception(_extractErrorMessage(decoded, response.statusCode));
}
final decoded = jsonDecode(response.body);
if (decoded is! Map<String, dynamic>) {
throw Exception('Réponse invalide du serveur.');
}
final token = decoded['token']?.toString().trim() ?? '';
if (token.isEmpty) {
throw Exception('Réponse invalide du serveur.');
}
return token;
}
/// Resoumission après refus. PATCH /auth/reprise-resoumettre. Ticket #112.
static Future<void> resoumettreReprise(Map<String, dynamic> body) async {
final cleaned = body['token']?.toString().trim() ?? '';