feat(inscription): email accusé réception, photos enfants, formulaires identité
- Backend: mail après inscription parent avec n° dossier, UPLOAD_PHOTOS_DIR, réponse API - Frontend: imageBytes + payload photo, utils email/code postal/téléphone, champs dédiés - Formulaires admin, login (focus), personal_info, child_card, custom_app_text_field Made-with: Cursor
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:p_tits_pas/utils/phone_utils.dart';
|
||||
import 'package:p_tits_pas/models/user.dart';
|
||||
import 'package:p_tits_pas/services/user_service.dart';
|
||||
import 'package:p_tits_pas/utils/email_utils.dart';
|
||||
import 'package:p_tits_pas/widgets/email_text_field.dart';
|
||||
import 'package:p_tits_pas/widgets/french_phone_field.dart';
|
||||
|
||||
class AdminCreateDialog extends StatefulWidget {
|
||||
final AppUser? initialUser;
|
||||
@@ -61,11 +63,10 @@ class _AdminCreateDialogState extends State<AdminCreateDialog> {
|
||||
|
||||
String? _validateEmail(String? value) {
|
||||
final base = _required(value, 'Email');
|
||||
if (base != null) return base;
|
||||
final email = value!.trim();
|
||||
final ok = RegExp(r'^[^@]+@[^@]+\.[^@]+$').hasMatch(email);
|
||||
if (!ok) return 'Format email invalide';
|
||||
return null;
|
||||
if (base != null) {
|
||||
return base;
|
||||
}
|
||||
return validateEmail(value, allowEmpty: true);
|
||||
}
|
||||
|
||||
String? _validatePassword(String? value) {
|
||||
@@ -78,6 +79,17 @@ class _AdminCreateDialogState extends State<AdminCreateDialog> {
|
||||
return null;
|
||||
}
|
||||
|
||||
String? _validateTelephone(String? value) {
|
||||
if (_isEditMode && (value == null || value.trim().isEmpty)) {
|
||||
return null;
|
||||
}
|
||||
final base = _required(value, 'Téléphone');
|
||||
if (base != null) {
|
||||
return base;
|
||||
}
|
||||
return validateFrenchNationalPhone(value, allowEmpty: false);
|
||||
}
|
||||
|
||||
Future<void> _submit() async {
|
||||
if (_isSubmitting) return;
|
||||
if (!_formKey.currentState!.validate()) return;
|
||||
@@ -305,13 +317,9 @@ class _AdminCreateDialogState extends State<AdminCreateDialog> {
|
||||
}
|
||||
|
||||
Widget _buildEmailField() {
|
||||
return TextFormField(
|
||||
return EmailTextFormField(
|
||||
controller: _emailController,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Email',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
label: 'Email',
|
||||
validator: _validateEmail,
|
||||
);
|
||||
}
|
||||
@@ -346,19 +354,10 @@ class _AdminCreateDialogState extends State<AdminCreateDialog> {
|
||||
}
|
||||
|
||||
Widget _buildTelephoneField() {
|
||||
return TextFormField(
|
||||
return FrenchPhoneTextFormField(
|
||||
controller: _telephoneController,
|
||||
keyboardType: TextInputType.phone,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
LengthLimitingTextInputFormatter(10),
|
||||
FrenchPhoneNumberFormatter(),
|
||||
],
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Téléphone (ex: 06 12 34 56 78)',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
validator: (v) => _required(v, 'Téléphone'),
|
||||
label: 'Téléphone (ex: 06 12 34 56 78)',
|
||||
validator: _validateTelephone,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user