petitspas/frontend/lib/widgets/auth/reprise_identify_dialog.dart
Julien Martin c438009286 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>
2026-06-16 17:01:18 +02:00

169 lines
5.0 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../../services/auth_service.dart';
import '../../utils/email_utils.dart';
import '../custom_app_text_field.dart';
/// Modale login : numéro de dossier + e-mail → token reprise (#112).
class RepriseIdentifyDialog extends StatefulWidget {
final String? initialEmail;
const RepriseIdentifyDialog({super.key, this.initialEmail});
@override
State<RepriseIdentifyDialog> createState() => _RepriseIdentifyDialogState();
}
class _RepriseIdentifyDialogState extends State<RepriseIdentifyDialog> {
final _formKey = GlobalKey<FormState>();
late final TextEditingController _numeroCtrl;
late final TextEditingController _emailCtrl;
bool _loading = false;
String? _error;
@override
void initState() {
super.initState();
_numeroCtrl = TextEditingController();
_emailCtrl = TextEditingController(text: widget.initialEmail ?? '');
}
@override
void dispose() {
_numeroCtrl.dispose();
_emailCtrl.dispose();
super.dispose();
}
String? _validateNumero(String? value) {
final v = value?.trim() ?? '';
if (v.isEmpty) {
return 'Indiquez votre numéro de dossier.';
}
return null;
}
String? _validateEmail(String? value) {
final v = value?.trim() ?? '';
if (v.isEmpty) {
return 'Indiquez votre adresse e-mail.';
}
if (!isValidEmailFormat(v)) {
return 'Ladresse e-mail nest pas valide.';
}
return null;
}
Future<void> _submit() async {
if (_loading) return;
setState(() => _error = null);
if (!(_formKey.currentState?.validate() ?? false)) return;
setState(() => _loading = true);
try {
final token = await AuthService.identifyReprise(
numeroDossier: _numeroCtrl.text,
email: _emailCtrl.text,
);
if (!mounted) return;
Navigator.of(context).pop(token);
} catch (e) {
if (!mounted) return;
setState(() {
_loading = false;
_error = e is Exception
? e.toString().replaceFirst('Exception: ', '')
: 'Impossible de retrouver votre dossier.';
});
}
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text(
'Reprendre mon dossier',
style: GoogleFonts.merienda(fontWeight: FontWeight.bold),
),
content: SizedBox(
width: 420,
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Saisissez le numéro de dossier et le-mail utilisés lors '
'de linscription (dossier refusé en attente de correction).',
style: GoogleFonts.merienda(fontSize: 13),
),
const SizedBox(height: 16),
CustomAppTextField(
controller: _numeroCtrl,
labelText: 'Numéro de dossier',
hintText: 'Ex. 2026-000021',
textInputAction: TextInputAction.next,
validator: _validateNumero,
style: CustomAppTextFieldStyle.lavande,
fieldHeight: 48,
fieldWidth: double.infinity,
),
const SizedBox(height: 12),
CustomAppTextField(
controller: _emailCtrl,
labelText: 'E-mail',
hintText: 'Votre adresse e-mail',
keyboardType: TextInputType.emailAddress,
autocorrect: false,
enableSuggestions: false,
inputFormatters: const [EmailMaxLengthFormatter()],
textInputAction: TextInputAction.done,
onFieldSubmitted: (_) => _submit(),
validator: _validateEmail,
style: CustomAppTextFieldStyle.lavande,
fieldHeight: 48,
fieldWidth: double.infinity,
),
if (_error != null) ...[
const SizedBox(height: 12),
Text(
_error!,
style: GoogleFonts.merienda(
fontSize: 12,
color: Colors.red.shade700,
),
),
],
],
),
),
),
actions: [
TextButton(
onPressed: _loading ? null : () => Navigator.of(context).pop(),
child: Text('Annuler', style: GoogleFonts.merienda()),
),
TextButton(
onPressed: _loading ? null : _submit,
child: _loading
? const SizedBox(
width: 18,
height: 18,
child: CircularProgressIndicator(strokeWidth: 2),
)
: Text(
'Continuer',
style: GoogleFonts.merienda(
fontWeight: FontWeight.bold,
color: const Color(0xFF2D6A4F),
),
),
),
],
);
}
}