Compare commits
2 Commits
master
...
feature/18
| Author | SHA1 | Date | |
|---|---|---|---|
| 2fb53d20cf | |||
| dfad408902 |
@ -200,10 +200,16 @@ export class AuthService {
|
||||
adresse: dto.adresse,
|
||||
code_postal: dto.code_postal,
|
||||
ville: dto.ville,
|
||||
profession: dto.profession,
|
||||
situation_familiale: dto.situation_familiale,
|
||||
token_creation_mdp: tokenCreationMdp,
|
||||
token_creation_mdp_expire_le: tokenExpiration,
|
||||
});
|
||||
|
||||
if (dto.date_naissance) {
|
||||
parent1.date_naissance = new Date(dto.date_naissance);
|
||||
}
|
||||
|
||||
const savedParent1 = await manager.save(Users, parent1);
|
||||
|
||||
// Créer Parent 2 si renseigné
|
||||
@ -321,10 +327,16 @@ export class AuthService {
|
||||
adresse: dto.adresse,
|
||||
code_postal: dto.code_postal,
|
||||
ville: dto.ville,
|
||||
profession: dto.profession,
|
||||
situation_familiale: dto.situation_familiale,
|
||||
token_creation_mdp: tokenCreationMdp,
|
||||
token_creation_mdp_expire_le: dateExpiration,
|
||||
});
|
||||
|
||||
if (dto.date_naissance) {
|
||||
parent1.date_naissance = new Date(dto.date_naissance);
|
||||
}
|
||||
|
||||
const parent1Enregistre = await manager.save(Users, parent1);
|
||||
|
||||
let parent2Enregistre: Users | null = null;
|
||||
|
||||
@ -66,6 +66,22 @@ export class RegisterParentCompletDto {
|
||||
@MaxLength(150)
|
||||
ville?: string;
|
||||
|
||||
@ApiProperty({ example: 'Infirmière', required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MaxLength(150)
|
||||
profession?: string;
|
||||
|
||||
@ApiProperty({ enum: SituationFamilialeType, example: SituationFamilialeType.MARIE, required: false })
|
||||
@IsOptional()
|
||||
@IsEnum(SituationFamilialeType)
|
||||
situation_familiale?: SituationFamilialeType;
|
||||
|
||||
@ApiProperty({ example: '1990-04-03', required: false })
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
date_naissance?: string;
|
||||
|
||||
// ============================================
|
||||
// ÉTAPE 2 : PARENT 2 / CO-PARENT (Optionnel)
|
||||
// ============================================
|
||||
|
||||
@ -59,6 +59,22 @@ export class RegisterParentDto {
|
||||
@MaxLength(150)
|
||||
ville?: string;
|
||||
|
||||
@ApiProperty({ example: 'Infirmière', required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MaxLength(150)
|
||||
profession?: string;
|
||||
|
||||
@ApiProperty({ enum: SituationFamilialeType, example: SituationFamilialeType.MARIE, required: false })
|
||||
@IsOptional()
|
||||
@IsEnum(SituationFamilialeType)
|
||||
situation_familiale?: SituationFamilialeType;
|
||||
|
||||
@ApiProperty({ example: '1990-04-03', required: false })
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
date_naissance?: string;
|
||||
|
||||
// === Informations co-parent (optionnel) ===
|
||||
@ApiProperty({ example: 'thomas.martin@ptits-pas.fr', required: false })
|
||||
@IsOptional()
|
||||
|
||||
@ -58,34 +58,32 @@ Ajouter un champ pour stocker la présentation du dossier parent (étape 4 de l'
|
||||
|
||||
---
|
||||
|
||||
### Ticket #3 : [BDD] Ajout gestion tokens création mot de passe ✅
|
||||
### Ticket #3 : [BDD] Ajout gestion tokens création mot de passe
|
||||
**Estimation** : 30min
|
||||
**Labels** : `bdd`, `p0-bloquant`, `security`
|
||||
**Statut** : ✅ TERMINÉ (Fermé le 2025-11-28)
|
||||
**Labels** : `bdd`, `p0-bloquant`, `security`
|
||||
|
||||
**Description** :
|
||||
Ajouter les champs nécessaires pour gérer les tokens de création de mot de passe (workflow sans MDP lors inscription).
|
||||
|
||||
**Tâches** :
|
||||
- [x] Ajouter `password_reset_token` UUID dans `utilisateurs`
|
||||
- [x] Ajouter `password_reset_expires` TIMESTAMPTZ dans `utilisateurs`
|
||||
- [x] Créer migration Prisma
|
||||
- [x] Tester migration
|
||||
- [ ] Ajouter `password_reset_token` UUID dans `utilisateurs`
|
||||
- [ ] Ajouter `password_reset_expires` TIMESTAMPTZ dans `utilisateurs`
|
||||
- [ ] Créer migration Prisma
|
||||
- [ ] Tester migration
|
||||
|
||||
---
|
||||
|
||||
### Ticket #4 : [BDD] Ajout champ genre obligatoire enfants ✅
|
||||
### Ticket #4 : [BDD] Ajout champ genre obligatoire enfants
|
||||
**Estimation** : 30min
|
||||
**Labels** : `bdd`, `p0-bloquant`, `cdc`
|
||||
**Statut** : ✅ TERMINÉ (Fermé le 2025-11-28)
|
||||
**Labels** : `bdd`, `p0-bloquant`, `cdc`
|
||||
|
||||
**Description** :
|
||||
Ajouter le champ `genre` obligatoire (H/F) dans la table `enfants`.
|
||||
|
||||
**Tâches** :
|
||||
- [x] Ajouter `genre` ENUM('H', 'F') NOT NULL dans `enfants`
|
||||
- [x] Créer migration Prisma
|
||||
- [x] Tester migration
|
||||
- [ ] Ajouter `genre` ENUM('H', 'F') NOT NULL dans `enfants`
|
||||
- [ ] Créer migration Prisma
|
||||
- [ ] Tester migration
|
||||
|
||||
---
|
||||
|
||||
@ -124,10 +122,9 @@ Créer la table `configuration` pour stocker les paramètres système (SMTP, app
|
||||
|
||||
---
|
||||
|
||||
### Ticket #7 : [BDD] Tables documents légaux & acceptations ✅
|
||||
### Ticket #7 : [BDD] Tables documents légaux & acceptations
|
||||
**Estimation** : 2h
|
||||
**Labels** : `bdd`, `p0-bloquant`, `rgpd`, `juridique`
|
||||
**Statut** : ✅ TERMINÉ (Fermé le 2025-11-30 - Ticket #68 sur Gitea)
|
||||
**Labels** : `bdd`, `p0-bloquant`, `rgpd`, `juridique`
|
||||
|
||||
**Description** :
|
||||
Créer les tables pour gérer les versions des documents légaux (CGU/Privacy) et tracer les acceptations utilisateurs.
|
||||
@ -337,13 +334,12 @@ Ajouter la gestion du co-parent (Parent 2) dans l'endpoint d'inscription.
|
||||
|
||||
---
|
||||
|
||||
### Ticket #18 : [Backend] API Inscription Parent - REFONTE (Workflow complet 6 étapes) ✅
|
||||
### Ticket #18 : [Backend] API Inscription Parent (étape 3 - Enfants)
|
||||
**Estimation** : 4h
|
||||
**Labels** : `backend`, `p2`, `auth`, `cdc`, `upload`
|
||||
**Statut** : ✅ TERMINÉ (Fermé le 2025-12-01)
|
||||
**Labels** : `backend`, `p2`, `auth`, `cdc`, `upload`
|
||||
|
||||
**Description** :
|
||||
Refonte complète de l'API d'inscription parent pour gérer le workflow complet en 6 étapes dans une seule transaction.
|
||||
Créer l'endpoint pour ajouter des enfants lors de l'inscription parent.
|
||||
|
||||
**Tâches** :
|
||||
- [ ] Endpoint `POST /api/v1/enfants`
|
||||
@ -356,13 +352,12 @@ Refonte complète de l'API d'inscription parent pour gérer le workflow complet
|
||||
|
||||
---
|
||||
|
||||
### Ticket #19 : [Backend] API Inscription Parent (étape 2 - Parent 2) ✅
|
||||
### Ticket #19 : [Backend] API Inscription Parent (étape 4-6 - Finalisation)
|
||||
**Estimation** : 2h
|
||||
**Labels** : `backend`, `p2`, `auth`, `cdc`
|
||||
**Statut** : ✅ TERMINÉ (Fermé le 2025-12-01)
|
||||
**Labels** : `backend`, `p2`, `auth`, `cdc`
|
||||
|
||||
**Description** :
|
||||
Gestion du co-parent (Parent 2) dans l'endpoint d'inscription (intégré dans la refonte #18).
|
||||
Finaliser l'inscription parent (présentation, CGU, récapitulatif).
|
||||
|
||||
**Tâches** :
|
||||
- [ ] Enregistrement présentation dossier
|
||||
@ -372,13 +367,12 @@ Gestion du co-parent (Parent 2) dans l'endpoint d'inscription (intégré dans la
|
||||
|
||||
---
|
||||
|
||||
### Ticket #20 : [Backend] API Inscription Parent (étape 3 - Enfants) ✅
|
||||
### Ticket #20 : [Backend] API Inscription AM (panneau 1 - Identité)
|
||||
**Estimation** : 4h
|
||||
**Labels** : `backend`, `p2`, `auth`, `cdc`, `upload`
|
||||
**Statut** : ✅ TERMINÉ (Fermé le 2025-12-01)
|
||||
**Labels** : `backend`, `p2`, `auth`, `cdc`, `upload`
|
||||
|
||||
**Description** :
|
||||
Gestion des enfants dans l'endpoint d'inscription (intégré dans la refonte #18).
|
||||
Créer l'endpoint d'inscription Assistante Maternelle (panneau 1/5 : identité).
|
||||
|
||||
**Tâches** :
|
||||
- [ ] Endpoint `POST /api/v1/auth/register/am`
|
||||
@ -392,13 +386,12 @@ Gestion des enfants dans l'endpoint d'inscription (intégré dans la refonte #18
|
||||
|
||||
---
|
||||
|
||||
### Ticket #21 : [Backend] API Inscription Parent (étape 4-6 - Finalisation) ✅
|
||||
### Ticket #21 : [Backend] API Inscription AM (panneau 2 - Infos pro)
|
||||
**Estimation** : 3h
|
||||
**Labels** : `backend`, `p2`, `auth`, `cdc`
|
||||
**Statut** : ✅ TERMINÉ (Fermé le 2025-12-01)
|
||||
**Labels** : `backend`, `p2`, `auth`, `cdc`
|
||||
|
||||
**Description** :
|
||||
Finalisation de l'inscription parent (présentation, CGU, récapitulatif - intégré dans la refonte #18).
|
||||
Ajouter les informations professionnelles de l'AM (panneau 2/5).
|
||||
|
||||
**Tâches** :
|
||||
- [ ] Validation NIR (15 chiffres obligatoire)
|
||||
@ -624,33 +617,22 @@ Créer l'écran de création de gestionnaire (super admin uniquement).
|
||||
|
||||
---
|
||||
|
||||
### Ticket #34 : [Réservé - Non utilisé]
|
||||
|
||||
---
|
||||
|
||||
### Ticket #35 : [Réservé - Non utilisé]
|
||||
|
||||
---
|
||||
|
||||
### Ticket #36 : [Frontend] Inscription Parent - Étape 1 (Parent 1) ✅
|
||||
### Ticket #34 : [Frontend] Inscription Parent - Étape 1 (Parent 1)
|
||||
**Estimation** : 3h
|
||||
**Labels** : `frontend`, `p3`, `auth`, `cdc`
|
||||
**Statut** : ✅ TERMINÉ (PR #73 mergée le 2025-12-01)
|
||||
**Labels** : `frontend`, `p3`, `auth`, `cdc`
|
||||
|
||||
**Description** :
|
||||
Créer le formulaire d'inscription parent - étape 1/6 (informations Parent 1).
|
||||
|
||||
**Tâches** :
|
||||
- [x] Formulaire identité Parent 1
|
||||
- [x] Validation côté client
|
||||
- [x] Pas de champ mot de passe
|
||||
- [x] Navigation vers étape 2
|
||||
- [x] Améliorations visuelles (labels 22px, champs 20px, espacement 32px)
|
||||
- [x] Correction indicateur étape 1/6
|
||||
- [ ] Formulaire identité Parent 1
|
||||
- [ ] Validation côté client
|
||||
- [ ] Pas de champ mot de passe
|
||||
- [ ] Navigation vers étape 2
|
||||
|
||||
---
|
||||
|
||||
### Ticket #37 : [Frontend] Inscription Parent - Étape 2 (Parent 2)
|
||||
### Ticket #35 : [Frontend] Inscription Parent - Étape 2 (Parent 2)
|
||||
**Estimation** : 3h
|
||||
**Labels** : `frontend`, `p3`, `auth`, `cdc`
|
||||
|
||||
@ -662,13 +644,10 @@ Créer le formulaire d'inscription parent - étape 2/6 (informations Parent 2 op
|
||||
- [ ] Formulaire identité Parent 2 (conditionnel)
|
||||
- [ ] Checkbox "Même adresse"
|
||||
- [ ] Navigation vers étape 3
|
||||
- [ ] Pas de champ mot de passe
|
||||
- [ ] Améliorations visuelles (mêmes que Step1)
|
||||
- [ ] Correction indicateur étape 2/6
|
||||
|
||||
---
|
||||
|
||||
### Ticket #38 : [Frontend] Inscription Parent - Étape 3 (Enfants)
|
||||
### Ticket #36 : [Frontend] Inscription Parent - Étape 3 (Enfants)
|
||||
**Estimation** : 4h
|
||||
**Labels** : `frontend`, `p3`, `auth`, `cdc`, `upload`
|
||||
|
||||
@ -685,7 +664,7 @@ Créer le formulaire d'inscription parent - étape 3/6 (informations enfants).
|
||||
|
||||
---
|
||||
|
||||
### Ticket #39 : [Frontend] Inscription Parent - Étapes 4-6 (Finalisation)
|
||||
### Ticket #37 : [Frontend] Inscription Parent - Étapes 4-6 (Finalisation)
|
||||
**Estimation** : 4h
|
||||
**Labels** : `frontend`, `p3`, `auth`, `cdc`
|
||||
|
||||
@ -702,7 +681,7 @@ Créer les étapes finales de l'inscription parent (présentation, CGU, récapit
|
||||
|
||||
---
|
||||
|
||||
### Ticket #40 : [Frontend] Inscription AM - Panneau 1 (Identité)
|
||||
### Ticket #38 : [Frontend] Inscription AM - Panneau 1 (Identité)
|
||||
**Estimation** : 3h
|
||||
**Labels** : `frontend`, `p3`, `auth`, `cdc`, `upload`
|
||||
|
||||
@ -718,7 +697,7 @@ Créer le formulaire d'inscription AM - panneau 1/5 (identité).
|
||||
|
||||
---
|
||||
|
||||
### Ticket #41 : [Frontend] Inscription AM - Panneau 2 (Infos pro)
|
||||
### Ticket #39 : [Frontend] Inscription AM - Panneau 2 (Infos pro)
|
||||
**Estimation** : 3h
|
||||
**Labels** : `frontend`, `p3`, `auth`, `cdc`
|
||||
|
||||
@ -734,7 +713,7 @@ Créer le formulaire d'inscription AM - panneau 2/5 (informations professionnell
|
||||
|
||||
---
|
||||
|
||||
### Ticket #42 : [Frontend] Inscription AM - Finalisation
|
||||
### Ticket #40 : [Frontend] Inscription AM - Finalisation
|
||||
**Estimation** : 3h
|
||||
**Labels** : `frontend`, `p3`, `auth`, `cdc`
|
||||
|
||||
@ -750,7 +729,7 @@ Créer les étapes finales de l'inscription AM (présentation, CGU, récapitulat
|
||||
|
||||
---
|
||||
|
||||
### Ticket #43 : [Frontend] Écran Création Mot de Passe
|
||||
### Ticket #41 : [Frontend] Écran Création Mot de Passe
|
||||
**Estimation** : 3h
|
||||
**Labels** : `frontend`, `p3`, `auth`
|
||||
|
||||
@ -767,7 +746,7 @@ Créer l'écran de création de mot de passe (lien reçu par email).
|
||||
|
||||
---
|
||||
|
||||
### Ticket #44 : [Frontend] Dashboard Gestionnaire - Structure
|
||||
### Ticket #42 : [Frontend] Dashboard Gestionnaire - Structure
|
||||
**Estimation** : 2h
|
||||
**Labels** : `frontend`, `p3`, `gestionnaire`
|
||||
|
||||
@ -781,7 +760,7 @@ Créer la structure du dashboard gestionnaire avec 2 onglets.
|
||||
|
||||
---
|
||||
|
||||
### Ticket #45 : [Frontend] Dashboard Gestionnaire - Liste Parents
|
||||
### Ticket #43 : [Frontend] Dashboard Gestionnaire - Liste Parents
|
||||
**Estimation** : 4h
|
||||
**Labels** : `frontend`, `p3`, `gestionnaire`
|
||||
|
||||
@ -797,7 +776,7 @@ Créer la liste des parents en attente de validation.
|
||||
|
||||
---
|
||||
|
||||
### Ticket #46 : [Frontend] Dashboard Gestionnaire - Liste AM
|
||||
### Ticket #44 : [Frontend] Dashboard Gestionnaire - Liste AM
|
||||
**Estimation** : 4h
|
||||
**Labels** : `frontend`, `p3`, `gestionnaire`
|
||||
|
||||
@ -814,7 +793,7 @@ Créer la liste des assistantes maternelles en attente de validation.
|
||||
|
||||
---
|
||||
|
||||
### Ticket #47 : [Frontend] Écran Changement MDP Obligatoire
|
||||
### Ticket #45 : [Frontend] Écran Changement MDP Obligatoire
|
||||
**Estimation** : 2h
|
||||
**Labels** : `frontend`, `p3`, `auth`, `security`
|
||||
|
||||
@ -830,7 +809,7 @@ Créer l'écran de changement de mot de passe obligatoire (première connexion g
|
||||
|
||||
---
|
||||
|
||||
### Ticket #48 : [Frontend] Gestion Erreurs & Messages
|
||||
### Ticket #46 : [Frontend] Gestion Erreurs & Messages
|
||||
**Estimation** : 2h
|
||||
**Labels** : `frontend`, `p3`, `ux`
|
||||
|
||||
@ -844,7 +823,7 @@ Créer un système de gestion des erreurs et messages utilisateur.
|
||||
|
||||
---
|
||||
|
||||
### Ticket #49 : [Frontend] Écran Gestion Documents Légaux (Admin)
|
||||
### Ticket #47 : [Frontend] Écran Gestion Documents Légaux (Admin)
|
||||
**Estimation** : 5h
|
||||
**Labels** : `frontend`, `p3`, `juridique`, `admin`
|
||||
|
||||
@ -863,7 +842,7 @@ Créer l'écran de gestion des documents légaux (CGU/Privacy) pour l'admin.
|
||||
|
||||
---
|
||||
|
||||
### Ticket #50 : [Frontend] Affichage dynamique CGU lors inscription
|
||||
### Ticket #48 : [Frontend] Affichage dynamique CGU lors inscription
|
||||
**Estimation** : 2h
|
||||
**Labels** : `frontend`, `p3`, `juridique`
|
||||
|
||||
@ -877,24 +856,9 @@ Afficher dynamiquement les CGU/Privacy lors de l'inscription (avec numéro de ve
|
||||
|
||||
---
|
||||
|
||||
### Ticket #51 : [Frontend] Écran Logs Admin (optionnel v1.1)
|
||||
**Estimation** : 4h
|
||||
**Labels** : `frontend`, `p3`, `admin`, `logs`
|
||||
|
||||
**Description** :
|
||||
Créer l'écran de consultation des logs système (optionnel pour v1.1).
|
||||
|
||||
**Tâches** :
|
||||
- [ ] Appel API logs
|
||||
- [ ] Filtres (date, niveau, utilisateur)
|
||||
- [ ] Pagination
|
||||
- [ ] Export CSV
|
||||
|
||||
---
|
||||
|
||||
## 🔵 PRIORITÉ 4 : Tests & Documentation
|
||||
|
||||
### Ticket #52 : [Tests] Tests unitaires Backend
|
||||
### Ticket #49 : [Tests] Tests unitaires Backend
|
||||
**Estimation** : 8h
|
||||
**Labels** : `tests`, `p4`, `backend`
|
||||
|
||||
|
||||
@ -22,9 +22,11 @@ class _ParentRegisterStep1ScreenState extends State<ParentRegisterStep1Screen> {
|
||||
final _firstNameController = TextEditingController();
|
||||
final _phoneController = TextEditingController();
|
||||
final _emailController = TextEditingController();
|
||||
final _addressController = TextEditingController();
|
||||
final _postalCodeController = TextEditingController();
|
||||
final _cityController = TextEditingController();
|
||||
final _passwordController = TextEditingController();
|
||||
final _confirmPasswordController = TextEditingController();
|
||||
final _addressController = TextEditingController(); // Rue seule
|
||||
final _postalCodeController = TextEditingController(); // Restauré
|
||||
final _cityController = TextEditingController(); // Restauré
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -46,6 +48,8 @@ class _ParentRegisterStep1ScreenState extends State<ParentRegisterStep1Screen> {
|
||||
_lastNameController.text = genLastName;
|
||||
_phoneController.text = DataGenerator.phone();
|
||||
_emailController.text = DataGenerator.email(genFirstName, genLastName);
|
||||
_passwordController.text = DataGenerator.password();
|
||||
_confirmPasswordController.text = _passwordController.text;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -54,6 +58,8 @@ class _ParentRegisterStep1ScreenState extends State<ParentRegisterStep1Screen> {
|
||||
_firstNameController.dispose();
|
||||
_phoneController.dispose();
|
||||
_emailController.dispose();
|
||||
_passwordController.dispose();
|
||||
_confirmPasswordController.dispose();
|
||||
_addressController.dispose();
|
||||
_postalCodeController.dispose();
|
||||
_cityController.dispose();
|
||||
@ -82,9 +88,9 @@ class _ParentRegisterStep1ScreenState extends State<ParentRegisterStep1Screen> {
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
// Indicateur d'étape
|
||||
// Indicateur d'étape (à rendre dynamique)
|
||||
Text(
|
||||
'Étape 1/6',
|
||||
'Étape 1/5',
|
||||
style: GoogleFonts.merienda(fontSize: 16, color: Colors.black54),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
@ -115,43 +121,54 @@ class _ParentRegisterStep1ScreenState extends State<ParentRegisterStep1Screen> {
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _lastNameController, labelText: 'Nom', hintText: 'Votre nom de famille', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)),
|
||||
Expanded(flex: 1, child: const SizedBox()),
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _firstNameController, labelText: 'Prénom', hintText: 'Votre prénom', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)),
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _lastNameController, labelText: 'Nom', hintText: 'Votre nom de famille', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)),
|
||||
Expanded(flex: 1, child: const SizedBox()), // Espace de 4%
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _firstNameController, labelText: 'Prénom', hintText: 'Votre prénom', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
const SizedBox(height: 20),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _phoneController, labelText: 'Téléphone', keyboardType: TextInputType.phone, hintText: 'Votre numéro de téléphone', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)),
|
||||
Expanded(flex: 1, child: const SizedBox()),
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _emailController, labelText: 'Email', keyboardType: TextInputType.emailAddress, hintText: 'Votre adresse e-mail', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)),
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _phoneController, labelText: 'Téléphone', keyboardType: TextInputType.phone, hintText: 'Votre numéro de téléphone', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)),
|
||||
Expanded(flex: 1, child: const SizedBox()), // Espace de 4%
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _emailController, labelText: 'Email', keyboardType: TextInputType.emailAddress, hintText: 'Votre adresse e-mail', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
const SizedBox(height: 20),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _passwordController, labelText: 'Mot de passe', obscureText: true, hintText: 'Créez votre mot de passe', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, validator: (value) {
|
||||
if (value == null || value.isEmpty) return 'Mot de passe requis';
|
||||
if (value.length < 6) return '6 caractères minimum';
|
||||
return null;
|
||||
})),
|
||||
Expanded(flex: 1, child: const SizedBox()), // Espace de 4%
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _confirmPasswordController, labelText: 'Confirmation', obscureText: true, hintText: 'Confirmez le mot de passe', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, validator: (value) {
|
||||
if (value == null || value.isEmpty) return 'Confirmation requise';
|
||||
if (value != _passwordController.text) return 'Ne correspond pas';
|
||||
return null;
|
||||
})),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
CustomAppTextField(
|
||||
controller: _addressController,
|
||||
labelText: 'Adresse (N° et Rue)',
|
||||
hintText: 'Numéro et nom de votre rue',
|
||||
style: CustomAppTextFieldStyle.beige,
|
||||
fieldWidth: double.infinity,
|
||||
labelFontSize: 22.0,
|
||||
inputFontSize: 20.0,
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
const SizedBox(height: 20),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(flex: 1, child: CustomAppTextField(controller: _postalCodeController, labelText: 'Code Postal', keyboardType: TextInputType.number, hintText: 'Code postal', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)),
|
||||
Expanded(flex: 1, child: CustomAppTextField(controller: _postalCodeController, labelText: 'Code Postal', keyboardType: TextInputType.number, hintText: 'Code postal', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)),
|
||||
const SizedBox(width: 20),
|
||||
Expanded(flex: 4, child: CustomAppTextField(controller: _cityController, labelText: 'Ville', hintText: 'Votre ville', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)),
|
||||
Expanded(flex: 4, child: CustomAppTextField(controller: _cityController, labelText: 'Ville', hintText: 'Votre ville', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -188,12 +205,12 @@ class _ParentRegisterStep1ScreenState extends State<ParentRegisterStep1Screen> {
|
||||
ParentData(
|
||||
firstName: _firstNameController.text,
|
||||
lastName: _lastNameController.text,
|
||||
address: _addressController.text,
|
||||
postalCode: _postalCodeController.text,
|
||||
city: _cityController.text,
|
||||
address: _addressController.text, // Rue
|
||||
postalCode: _postalCodeController.text, // Ajout
|
||||
city: _cityController.text, // Ajout
|
||||
phone: _phoneController.text,
|
||||
email: _emailController.text,
|
||||
password: '', // Pas de mot de passe à cette étape
|
||||
password: _passwordController.text,
|
||||
)
|
||||
);
|
||||
Navigator.pushNamed(context, '/parent-register/step2', arguments: _registrationData);
|
||||
|
||||
@ -22,14 +22,16 @@ class _ParentRegisterStep2ScreenState extends State<ParentRegisterStep2Screen> {
|
||||
bool _addParent2 = true; // Pour le test, on ajoute toujours le parent 2
|
||||
bool _sameAddressAsParent1 = false; // Peut être généré aléatoirement aussi
|
||||
|
||||
// Contrôleurs pour les champs du parent 2
|
||||
// Contrôleurs pour les champs du parent 2 (restauration CP et Ville)
|
||||
final _lastNameController = TextEditingController();
|
||||
final _firstNameController = TextEditingController();
|
||||
final _phoneController = TextEditingController();
|
||||
final _emailController = TextEditingController();
|
||||
final _addressController = TextEditingController();
|
||||
final _postalCodeController = TextEditingController();
|
||||
final _cityController = TextEditingController();
|
||||
final _passwordController = TextEditingController();
|
||||
final _confirmPasswordController = TextEditingController();
|
||||
final _addressController = TextEditingController(); // Rue seule
|
||||
final _postalCodeController = TextEditingController(); // Restauré
|
||||
final _cityController = TextEditingController(); // Restauré
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -47,13 +49,17 @@ class _ParentRegisterStep2ScreenState extends State<ParentRegisterStep2Screen> {
|
||||
_lastNameController.text = genLastName;
|
||||
_phoneController.text = DataGenerator.phone();
|
||||
_emailController.text = DataGenerator.email(genFirstName, genLastName);
|
||||
_passwordController.text = DataGenerator.password();
|
||||
_confirmPasswordController.text = _passwordController.text;
|
||||
|
||||
_sameAddressAsParent1 = DataGenerator.boolean();
|
||||
if (!_sameAddressAsParent1) {
|
||||
// Générer adresse, CP, Ville séparément
|
||||
_addressController.text = DataGenerator.address();
|
||||
_postalCodeController.text = DataGenerator.postalCode();
|
||||
_cityController.text = DataGenerator.city();
|
||||
} else {
|
||||
// Vider les champs si même adresse (seront désactivés)
|
||||
_addressController.clear();
|
||||
_postalCodeController.clear();
|
||||
_cityController.clear();
|
||||
@ -66,6 +72,8 @@ class _ParentRegisterStep2ScreenState extends State<ParentRegisterStep2Screen> {
|
||||
_firstNameController.dispose();
|
||||
_phoneController.dispose();
|
||||
_emailController.dispose();
|
||||
_passwordController.dispose();
|
||||
_confirmPasswordController.dispose();
|
||||
_addressController.dispose();
|
||||
_postalCodeController.dispose();
|
||||
_cityController.dispose();
|
||||
@ -90,7 +98,7 @@ class _ParentRegisterStep2ScreenState extends State<ParentRegisterStep2Screen> {
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('Étape 2/6', style: GoogleFonts.merienda(fontSize: 16, color: Colors.black54)),
|
||||
Text('Étape 2/5', style: GoogleFonts.merienda(fontSize: 16, color: Colors.black54)),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
'Informations du Deuxième Parent (Optionnel)',
|
||||
@ -109,9 +117,7 @@ class _ParentRegisterStep2ScreenState extends State<ParentRegisterStep2Screen> {
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
@ -150,33 +156,40 @@ class _ParentRegisterStep2ScreenState extends State<ParentRegisterStep2Screen> {
|
||||
]),
|
||||
),
|
||||
]),
|
||||
const SizedBox(height: 32),
|
||||
const SizedBox(height: 25),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _lastNameController, labelText: 'Nom', hintText: 'Nom du parent 2', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)),
|
||||
Expanded(flex: 1, child: const SizedBox()),
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _firstNameController, labelText: 'Prénom', hintText: 'Prénom du parent 2', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)),
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _lastNameController, labelText: 'Nom', hintText: 'Nom du parent 2', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)),
|
||||
Expanded(flex: 1, child: const SizedBox()), // Espace de 4%
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _firstNameController, labelText: 'Prénom', hintText: 'Prénom du parent 2', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
const SizedBox(height: 20),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _phoneController, labelText: 'Téléphone', keyboardType: TextInputType.phone, hintText: 'Son téléphone', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)),
|
||||
Expanded(flex: 1, child: const SizedBox()),
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _emailController, labelText: 'Email', keyboardType: TextInputType.emailAddress, hintText: 'Son email', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)),
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _phoneController, labelText: 'Téléphone', keyboardType: TextInputType.phone, hintText: 'Son téléphone', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)),
|
||||
Expanded(flex: 1, child: const SizedBox()), // Espace de 4%
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _emailController, labelText: 'Email', keyboardType: TextInputType.emailAddress, hintText: 'Son email', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
CustomAppTextField(controller: _addressController, labelText: 'Adresse (N° et Rue)', hintText: 'Son numéro et nom de rue', enabled: _addressFieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0),
|
||||
const SizedBox(height: 32),
|
||||
const SizedBox(height: 20),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(flex: 1, child: CustomAppTextField(controller: _postalCodeController, labelText: 'Code Postal', keyboardType: TextInputType.number, hintText: 'Son code postal', enabled: _addressFieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)),
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _passwordController, labelText: 'Mot de passe', obscureText: true, hintText: 'Son mot de passe', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, validator: _addParent2 ? (v) => (v == null || v.isEmpty ? 'Requis' : (v.length < 6 ? '6 car. min' : null)) : null)),
|
||||
Expanded(flex: 1, child: const SizedBox()), // Espace de 4%
|
||||
Expanded(flex: 12, child: CustomAppTextField(controller: _confirmPasswordController, labelText: 'Confirmation', obscureText: true, hintText: 'Confirmer mot de passe', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, validator: _addParent2 ? (v) => (v == null || v.isEmpty ? 'Requis' : (v != _passwordController.text ? 'Différent' : null)) : null)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
CustomAppTextField(controller: _addressController, labelText: 'Adresse (N° et Rue)', hintText: 'Son numéro et nom de rue', enabled: _addressFieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity),
|
||||
const SizedBox(height: 20),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(flex: 1, child: CustomAppTextField(controller: _postalCodeController, labelText: 'Code Postal', keyboardType: TextInputType.number, hintText: 'Son code postal', enabled: _addressFieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)),
|
||||
const SizedBox(width: 20),
|
||||
Expanded(flex: 4, child: CustomAppTextField(controller: _cityController, labelText: 'Ville', hintText: 'Sa ville', enabled: _addressFieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)),
|
||||
Expanded(flex: 4, child: CustomAppTextField(controller: _cityController, labelText: 'Ville', hintText: 'Sa ville', enabled: _addressFieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -212,7 +225,7 @@ class _ParentRegisterStep2ScreenState extends State<ParentRegisterStep2Screen> {
|
||||
city: _sameAddressAsParent1 ? _registrationData.parent1.city : _cityController.text,
|
||||
phone: _phoneController.text,
|
||||
email: _emailController.text,
|
||||
password: '', // Pas de mot de passe à cette étape
|
||||
password: _passwordController.text,
|
||||
)
|
||||
);
|
||||
} else {
|
||||
@ -231,10 +244,8 @@ class _ParentRegisterStep2ScreenState extends State<ParentRegisterStep2Screen> {
|
||||
|
||||
void _clearParent2Fields() {
|
||||
_formKey.currentState?.reset();
|
||||
_lastNameController.clear();
|
||||
_firstNameController.clear();
|
||||
_phoneController.clear();
|
||||
_emailController.clear();
|
||||
_lastNameController.clear(); _firstNameController.clear(); _phoneController.clear();
|
||||
_emailController.clear(); _passwordController.clear(); _confirmPasswordController.clear();
|
||||
_addressController.clear();
|
||||
_postalCodeController.clear();
|
||||
_cityController.clear();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user