diff --git a/docs/00_INDEX.md b/docs/00_INDEX.md index 062e0f7..df689ca 100644 --- a/docs/00_INDEX.md +++ b/docs/00_INDEX.md @@ -27,6 +27,7 @@ Ce fichier sert d'index pour naviguer dans toute la documentation du projet. - [**23 - Liste des Tickets**](./23_LISTE-TICKETS.md) - 61 tickets Phase 1 détaillés - [**24 - Décisions Projet**](./24_DECISIONS-PROJET.md) - Décisions architecturales et fonctionnelles - [**25 - Backlog Phase 2**](./25_PHASE-2-BACKLOG.md) - Fonctionnalités techniques reportées +- [**26 - API Gitea**](./26_GITEA-API.md) - Procédure d'utilisation de l'API Gitea (issues, PR, branches, labels) ### Administration (À créer) - [**30 - Guide d'administration**](./30_ADMIN.md) - Gestion des utilisateurs, accès PgAdmin, logs diff --git a/docs/23_LISTE-TICKETS.md b/docs/23_LISTE-TICKETS.md index 087a6ad..eb005fd 100644 --- a/docs/23_LISTE-TICKETS.md +++ b/docs/23_LISTE-TICKETS.md @@ -3,7 +3,33 @@ **Version** : 1.2 **Date** : 27 Janvier 2026 **Auteur** : Équipe PtitsPas -**Estimation totale** : ~173h +**Estimation totale** : ~184h + +--- + +## 🔗 Liste des tickets Gitea + +Correspondance entre les numéros d’issues Gitea et les tickets de ce document. + +| Gitea # | Titre court | Priorité | Statut | Section doc | +|--------|--------------|----------|--------|-------------| +| 1 | BDD - Champs manquants CDC | P0 | Ouvert | § Ticket #1 | +| 2 | BDD - Table présentation dossier parent | P0 | Ouvert | § Ticket #2 | +| 3 | BDD - Tokens création MDP | P0 | ✅ Fermé | § Ticket #3 | +| 4 | BDD - Champ genre enfants | P0 | ✅ Fermé | § Ticket #4 | +| 5 | BDD - Supprimer champs obsolètes | P0 | Ouvert | § Ticket #5 | +| 6 | BDD - Table configuration système | P0 | Ouvert | § Ticket #6 | +| 68 | BDD - Documents légaux & acceptations | P0 | ✅ Fermé | § Ticket #7 | +| 73 | Frontend - Inscription Parent Étape 1 | P3 | ✅ Fermé (PR) | § Ticket #36 | +| 78 | Frontend - Infrastructure formulaires multi-modes | P3 | ✅ Fermé | § Ticket #78 | +| 79 | Frontend - Renommer Nanny en AM | P3 | ✅ Fermé | § Ticket #79 | +| 81 | Frontend - Corrections refactoring widgets | P3 | ✅ Fermé | § Ticket #81 | +| 82 | Frontend - Écran Login mobile | P3 | ✅ Fermé | § Ticket #82 | +| 83 | Frontend - RegisterChoiceScreen mobile | P3 | ✅ Fermé | § Ticket #83 | + +*Les autres tickets (sans numéro Gitea dans ce tableau) sont décrits dans les sections par priorité ci‑dessous ; les numéros de section (#1 à #83) sont les références internes du document.* + +**Point API (tickets frontend)** – 27/01/2026 : 20 issues avec le label `frontend` dans Gitea (12 ouvertes, 8 fermées). Numéros concernés : 35–42, 43–51, 54, 82, 83. Les #73, #78, #79, #81 sont fermés mais sans label dans l’API. Détail : `docs/POINT_TICKETS_FRONT_API.txt`. --- @@ -43,11 +69,11 @@ Correspondance entre les numéros d’issues Gitea et les tickets de ce document | **P0** | 7 tickets | ~5h | Amendements BDD (BLOQUANT) | | **P1** | 7 tickets | ~22h | Configuration système (BLOQUANT) | | **P2** | 18 tickets | ~50h | Backend métier | -| **P3** | 17 tickets | ~52h | Frontend | +| **P3** | 22 tickets | ~71h | Frontend | | **P4** | 4 tickets | ~24h | Tests & Documentation | | **CRITIQUES** | 6 tickets | ~13h | Upload, Logs, Infra, CDC | | **JURIDIQUE** | 1 ticket | ~8h | Rédaction CGU/Privacy | -| **TOTAL** | **62 tickets** | **~181h** | | +| **TOTAL** | **65 tickets** | **~184h** | | --- @@ -695,85 +721,90 @@ Créer le formulaire d'inscription parent - étape 2/6 (informations Parent 2 op --- -### Ticket #38 : [Frontend] Inscription Parent - Étape 3 (Enfants) -**Estimation** : 4h +### Ticket #38 : [Frontend] Inscription Parent - Étape 3 (Enfants) ✅ +**Estimation** : 4h **Labels** : `frontend`, `p3`, `auth`, `cdc`, `upload` +**Statut** : ✅ TERMINÉ (Fermé le 2026-02-07) **Description** : Créer le formulaire d'inscription parent - étape 3/6 (informations enfants). **Tâches** : -- [ ] Question "Enfant déjà né ?" -- [ ] Formulaire enfant (prénom, date, genre H/F obligatoire) -- [ ] Upload photo (si né) -- [ ] Validation taille (5MB) -- [ ] Bouton "Ajouter un autre enfant" -- [ ] Navigation vers étape 4 +- [x] Question "Enfant déjà né ?" +- [x] Formulaire enfant (prénom, date, genre H/F obligatoire) +- [x] Upload photo (si né) +- [x] Validation taille (5MB) +- [x] Bouton "Ajouter un autre enfant" +- [x] Navigation vers étape 4 --- -### Ticket #39 : [Frontend] Inscription Parent - Étapes 4-6 (Finalisation) -**Estimation** : 4h +### Ticket #39 : [Frontend] Inscription Parent - Étapes 4-6 (Finalisation) ✅ +**Estimation** : 4h **Labels** : `frontend`, `p3`, `auth`, `cdc` +**Statut** : ✅ TERMINÉ (Fermé le 2026-02-07) **Description** : Créer les étapes finales de l'inscription parent (présentation, CGU, récapitulatif). **Tâches** : -- [ ] Étape 4 : Textarea présentation -- [ ] Étape 5 : Checkbox CGU + liens PDF -- [ ] Étape 6 : Récapitulatif complet -- [ ] Bouton "Modifier" / "Valider" -- [ ] Appel API final -- [ ] Message confirmation +- [x] Étape 4 : Textarea présentation +- [x] Étape 5 : Checkbox CGU + liens PDF +- [x] Étape 6 : Récapitulatif complet +- [x] Bouton "Modifier" / "Valider" +- [x] Appel API final +- [x] Message confirmation --- -### Ticket #40 : [Frontend] Inscription AM - Panneau 1 (Identité) -**Estimation** : 3h +### Ticket #40 : [Frontend] Inscription AM - Panneau 1 (Identité) ✅ +**Estimation** : 3h **Labels** : `frontend`, `p3`, `auth`, `cdc`, `upload` +**Statut** : ✅ TERMINÉ (Fermé le 2026-02-07) **Description** : Créer le formulaire d'inscription AM - panneau 1/5 (identité). **Tâches** : -- [ ] Formulaire identité -- [ ] Upload photo -- [ ] Checkbox consentement photo -- [ ] Pas de champ mot de passe -- [ ] Navigation vers panneau 2 +- [x] Formulaire identité +- [x] Upload photo +- [x] Checkbox consentement photo +- [x] Pas de champ mot de passe +- [x] Navigation vers panneau 2 --- -### Ticket #41 : [Frontend] Inscription AM - Panneau 2 (Infos pro) -**Estimation** : 3h +### Ticket #41 : [Frontend] Inscription AM - Panneau 2 (Infos pro) ✅ +**Estimation** : 3h **Labels** : `frontend`, `p3`, `auth`, `cdc` +**Statut** : ✅ TERMINÉ (Fermé le 2026-02-07) **Description** : Créer le formulaire d'inscription AM - panneau 2/5 (informations professionnelles). **Tâches** : -- [ ] Formulaire infos pro -- [ ] Champ NIR (15 chiffres, validation) -- [ ] Date/lieu naissance -- [ ] Agrément + date obtention -- [ ] Navigation vers présentation +- [x] Formulaire infos pro +- [x] Champ NIR (15 chiffres, validation) +- [x] Date/lieu naissance +- [x] Agrément + date obtention +- [x] Navigation vers présentation --- -### Ticket #42 : [Frontend] Inscription AM - Finalisation -**Estimation** : 3h +### Ticket #42 : [Frontend] Inscription AM - Finalisation ✅ +**Estimation** : 3h **Labels** : `frontend`, `p3`, `auth`, `cdc` +**Statut** : ✅ TERMINÉ (Fermé le 2026-02-07) **Description** : Créer les étapes finales de l'inscription AM (présentation, CGU, récapitulatif). **Tâches** : -- [ ] Textarea présentation -- [ ] Checkbox CGU + liens PDF -- [ ] Récapitulatif (NIR masqué) -- [ ] Appel API final -- [ ] Message confirmation +- [x] Textarea présentation +- [x] Checkbox CGU + liens PDF +- [x] Récapitulatif (NIR masqué) +- [x] Appel API final +- [x] Message confirmation --- @@ -972,6 +1003,56 @@ Créer une infrastructure générique pour gérer les formulaires en modes multi --- +### Ticket #79 : [Frontend] Renommer "Nanny" en "Assistante Maternelle" (AM) ✅ +**Estimation** : 2h +**Labels** : `frontend`, `p3`, `refactoring`, `cdc` +**Statut** : ✅ TERMINÉ (Fermé le 2026-02-07) + +**Description** : +Renommage complet de "Nanny" en "AM" dans le frontend pour cohérence avec le CDC. + +**Tâches** : +- [x] Modèles : nanny_registration_data.dart -> am_registration_data.dart +- [x] Écrans : nanny_register_*.dart -> am_register_*.dart +- [x] Routes : /nanny-register -> /am-register +- [x] Suppression fichiers obsolètes + +--- + +### Ticket #81 : [Frontend] Corrections suite refactoring widgets ✅ +**Estimation** : 2h +**Labels** : `frontend`, `p3`, `bugfix` +**Statut** : ✅ TERMINÉ (Fermé le 2026-02-07) + +**Description** : +Corrections et ajustements suite au refactoring des widgets. + +**Corrections :** +- [x] Erreurs compilation (updateParent1/2, updateIdentityInfo) +- [x] Routes obsolètes supprimées +- [x] Toggles Parent Step 2 (2 côte à côte) +- [x] Positionnement éléments dans cartes + +--- + +### Ticket #83 : [Frontend] Adapter RegisterChoiceScreen pour mobile ✅ +**Estimation** : 3h +**Labels** : `frontend`, `p3`, `responsive`, `ux` +**Statut** : ✅ TERMINÉ (Fermé le 2026-01-27) + +**Description** : +Adapter l'écran de choix Parent/AM pour une meilleure expérience mobile et cohérence avec les autres écrans. + +**Tâches :** +- [x] Implémentation responsive avec LayoutBuilder (mobile < 900px) +- [x] Mode mobile : titre au-dessus, carte pleine largeur (ratio 2/3), boutons verticaux +- [x] Mode desktop : chevron haut-gauche, layout texte/carte côte à côte +- [x] Extraction logique carte dans ChoiceCardWidget réutilisable +- [x] Bouton "Précédent" mobile avec CustomNavigationButton + HoverReliefWidget +- [x] Tailles icônes augmentées (140px mobile, 170px desktop) + +--- + ## 🔵 PRIORITÉ 4 : Tests & Documentation ### Ticket #52 : [Tests] Tests unitaires Backend @@ -1198,15 +1279,15 @@ Rédiger les documents légaux génériques (CGU et Politique de confidentialit - **P2 (Backend)** : 18 tickets (~50h) - **P3 (Frontend)** : 20 tickets (~62h) ← #84 bug connexion admin, #85 correctifs modale MDP - **P4 (Tests/Doc)** : 4 tickets (~24h) -- **Critiques** : 6 tickets (~13h) ← -2 email, +1 logs, +1 CDC +- **Critiques** : 6 tickets (~13h) - **Juridique** : 1 ticket (~8h) ### Par domaine - **BDD** : 7 tickets -- **Backend** : 23 tickets ← +1 logs +- **Backend** : 23 tickets - **Frontend** : 20 tickets ← #84 bug connexion admin, #85 correctifs modale MDP - **Tests** : 3 tickets -- **Documentation** : 5 tickets ← +1 amendement CDC +- **Documentation** : 5 tickets - **Infra** : 2 tickets - **Juridique** : 1 ticket @@ -1215,8 +1296,12 @@ Rédiger les documents légaux génériques (CGU et Politique de confidentialit - ✅ **Ajouté** : Ticket #55 "Service Logging Winston" - Monitoring essentiel - ✅ **Ajouté** : Ticket #56 "Écran Logs Admin" - Optionnel Phase 1.1 - ✅ **Ajouté** : Ticket #78 "Refonte Infrastructure Formulaires" - Harmonisation UI/UX +- ✅ **Ajouté** : Ticket #79 "Renommer Nanny en AM" - Cohérence CDC +- ✅ **Ajouté** : Ticket #81 "Corrections refactoring" - Bugfixes +- ✅ **Ajouté** : Ticket #83 "RegisterChoiceScreen Mobile" - Responsive UX +- ✅ **Fermé** : Ticket #82 "Écran Login mobile" - Merge develop + master - ✅ **Ajouté** : Ticket #84 "Bug connexion admin – erreur profil et redirection" (Gitea #84, fermé) -- ✅ **Ajouté** : Ticket #85 "Bug – Correctifs modale Changement MDP" (Gitea #85) - Design, UX, validations, lien test debug +- ✅ **Ajouté** : Ticket #85 "Bug – Correctifs modale Changement MDP" (Gitea #85) --- diff --git a/docs/26_GITEA-API.md b/docs/26_GITEA-API.md new file mode 100644 index 0000000..1cbea2e --- /dev/null +++ b/docs/26_GITEA-API.md @@ -0,0 +1,176 @@ +# Procédure – Utilisation de l'API Gitea + +## 1. Contexte + +- **Instance** : https://git.ptits-pas.fr +- **API de base** : `https://git.ptits-pas.fr/api/v1` +- **Projet P'titsPas** : dépôt `jmartin/petitspas` (owner = `jmartin`, repo = `petitspas`) + +## 2. Authentification + +### 2.1 Token + +Le token est défini dans l'environnement (ex. `~/.bashrc`) : + +```bash +export GITEA_TOKEN="" +``` + +Pour l'utiliser dans les commandes : + +```bash +source ~/.bashrc # ou : . ~/.bashrc +# Puis utiliser $GITEA_TOKEN dans les curl +``` + +### 2.2 En-tête HTTP + +Toutes les requêtes API doivent envoyer le token : + +```bash +-H "Authorization: token $GITEA_TOKEN" +``` + +Exemple : + +```bash +curl -s -H "Authorization: token $GITEA_TOKEN" \ + "https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas" +``` + +## 3. Endpoints utiles + +### 3.1 Dépôt (repository) + +| Action | Méthode | URL | +|---------------|---------|-----| +| Infos dépôt | GET | `/repos/{owner}/{repo}` | +| Liste dépôts | GET | `/repos/search?q=petitspas` | + +Exemple – infos du dépôt : + +```bash +curl -s -H "Authorization: token $GITEA_TOKEN" \ + "https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas" | jq . +``` + +### 3.2 Issues (tickets) + +| Action | Méthode | URL | +|------------------|---------|-----| +| Liste des issues | GET | `/repos/{owner}/{repo}/issues` | +| Détail d'une issue | GET | `/repos/{owner}/{repo}/issues/{index}` | +| Créer une issue | POST | `/repos/{owner}/{repo}/issues` | +| Modifier une issue | PATCH | `/repos/{owner}/{repo}/issues/{index}` | +| Fermer une issue | PATCH | (même URL, `state: "closed"`) | + +**Paramètres GET utiles pour la liste :** + +- `state` : `open` ou `closed` +- `labels` : filtre par label (ex. `frontend`) +- `page`, `limit` : pagination + +Exemples : + +```bash +# Toutes les issues ouvertes +curl -s -H "Authorization: token $GITEA_TOKEN" \ + "https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas/issues?state=open" | jq . + +# Issues ouvertes avec label "frontend" +curl -s -H "Authorization: token $GITEA_TOKEN" \ + "https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas/issues?state=open" | \ + jq '.[] | select(.labels[].name == "frontend") | {number, title, state}' + +# Détail de l'issue #47 +curl -s -H "Authorization: token $GITEA_TOKEN" \ + "https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas/issues/47" | jq . + +# Fermer l'issue #31 +curl -s -X PATCH -H "Authorization: token $GITEA_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"state":"closed"}' \ + "https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas/issues/31" + +# Créer une issue +curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"title":"Titre du ticket","body":"Description","labels":[1]}' \ + "https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas/issues" +``` + +### 3.3 Pull requests + +| Action | Méthode | URL | +|---------------|---------|-----| +| Liste des PR | GET | `/repos/{owner}/{repo}/pulls` | +| Détail d'une PR | GET | `/repos/{owner}/{repo}/pulls/{index}` | +| Créer une PR | POST | `/repos/{owner}/{repo}/pulls` | +| Fusionner une PR | POST | `/repos/{owner}/{repo}/pulls/{index}/merge` | + +Exemples : + +```bash +# Liste des PR ouvertes +curl -s -H "Authorization: token $GITEA_TOKEN" \ + "https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas/pulls?state=open" | jq . + +# Créer une PR (head = branche source, base = branche cible) +curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"head":"develop","base":"master","title":"Titre de la PR"}' \ + "https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas/pulls" +``` + +### 3.4 Branches + +| Action | Méthode | URL | +|---------------|---------|-----| +| Liste des branches | GET | `/repos/{owner}/{repo}/branches` | + +```bash +curl -s -H "Authorization: token $GITEA_TOKEN" \ + "https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas/branches" | jq '.[].name' +``` + +### 3.5 Webhooks + +| Action | Méthode | URL | +|---------------|---------|-----| +| Liste webhooks | GET | `/repos/{owner}/{repo}/hooks` | +| Créer webhook | POST | `/repos/{owner}/{repo}/hooks` | + +### 3.6 Labels + +| Action | Méthode | URL | +|---------------|---------|-----| +| Liste des labels | GET | `/repos/{owner}/{repo}/labels` | + +```bash +curl -s -H "Authorization: token $GITEA_TOKEN" \ + "https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas/labels" | jq '.[] | {id, name}' +``` + +## 4. Résumé des URLs pour P'titsPas + +Remplacer `{owner}` par `jmartin` et `{repo}` par `petitspas` : + +| Ressource | URL | +|------------------|-----| +| Dépôt | `https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas` | +| Issues | `https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas/issues` | +| Issue #n | `https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas/issues/{n}` | +| Pull requests | `https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas/pulls` | +| Branches | `https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas/branches` | +| Labels | `https://git.ptits-pas.fr/api/v1/repos/jmartin/petitspas/labels` | + +## 5. Documentation officielle + +- Swagger / OpenAPI : https://docs.gitea.com/api +- Référence selon la version de Gitea installée (ex. 1.21, 1.25). + +## 6. Dépannage + +- **401 Unauthorized** : vérifier le token et l'en-tête `Authorization: token `. +- **404** : vérifier owner/repo et l'URL (sensible à la casse). +- **422 / body invalide** : pour POST/PATCH, envoyer `Content-Type: application/json` et un JSON valide. diff --git a/docs/POINT_TICKETS_FRONT_API.txt b/docs/POINT_TICKETS_FRONT_API.txt new file mode 100644 index 0000000..f78be3d --- /dev/null +++ b/docs/POINT_TICKETS_FRONT_API.txt @@ -0,0 +1,35 @@ +Point tickets frontend (API Gitea) - 27/01/2026 +================================================ + +Issues avec label "frontend" : 20 (ouvertes: 12, fermees: 8) + +Num | Etat | Titre +----+--------+-------------------------------------------------------- + 35 | open | [Frontend] Écran Création Gestionnaire + 36 | closed | [Frontend] Inscription Parent - Étape 1 (Parent 1) + 37 | closed | [Frontend] Inscription Parent - Étape 2 (Parent 2) + 38 | closed | [Frontend] Inscription Parent - Étape 3 (Enfants) + 39 | closed | [Frontend] Inscription Parent - Étapes 4-6 (Finalisatio + 40 | closed | [Frontend] Inscription AM - Panneau 1 (Identité) + 41 | closed | [Frontend] Inscription AM - Panneau 2 (Infos pro) + 42 | closed | [Frontend] Inscription AM - Finalisation + 43 | open | [Frontend] Écran Création Mot de Passe + 44 | open | [Frontend] Dashboard Gestionnaire - Structure + 45 | open | [Frontend] Dashboard Gestionnaire - Liste Parents + 46 | open | [Frontend] Dashboard Gestionnaire - Liste AM + 47 | open | [Frontend] Écran Changement MDP Obligatoire + 48 | open | [Frontend] Gestion Erreurs & Messages + 49 | open | [Frontend] Écran Gestion Documents Légaux (Admin) + 50 | open | [Frontend] Affichage dynamique CGU lors inscription + 51 | open | [Frontend] Écran Logs Admin (optionnel v1.1) + 54 | open | [Tests] Tests E2E Frontend + 82 | closed | [Frontend] Adapter �cran Login pour mobile + 83 | closed | [Frontend] Adapter �cran Choix Inscription pour mobile + +Suivi doc 23_LISTE-TICKETS (Gitea #73,78,79,81,82,83): + #73 closed labels=[] + #78 closed labels=[] + #79 closed labels=[] + #81 closed labels=[] + #82 closed (écran Login mobile) + #83 closed labels=['frontend', 'p3', 'phase-1', 'ux'] diff --git a/frontend/lib/config/app_router.dart b/frontend/lib/config/app_router.dart index 7bd6358..d5e2ad6 100644 --- a/frontend/lib/config/app_router.dart +++ b/frontend/lib/config/app_router.dart @@ -19,6 +19,8 @@ import '../screens/auth/am_register_step2_screen.dart'; import '../screens/auth/am_register_step3_screen.dart'; import '../screens/auth/am_register_step4_screen.dart'; import '../screens/home/home_screen.dart'; +import '../screens/administrateurs/admin_dashboardScreen.dart'; +import '../screens/home/parent_screen/ParentDashboardScreen.dart'; import '../screens/unknown_screen.dart'; // --- Provider Instances --- @@ -47,6 +49,18 @@ class AppRouter { path: '/home', builder: (BuildContext context, GoRouterState state) => const HomeScreen(), ), + GoRoute( + path: '/admin-dashboard', + builder: (BuildContext context, GoRouterState state) => const AdminDashboardScreen(), + ), + GoRoute( + path: '/parent-dashboard', + builder: (BuildContext context, GoRouterState state) => const ParentDashboardScreen(), + ), + GoRoute( + path: '/am-dashboard', + builder: (BuildContext context, GoRouterState state) => const HomeScreen(), + ), // --- Parent Registration Flow --- ShellRoute( diff --git a/frontend/lib/models/nanny_registration_data.dart b/frontend/lib/models/nanny_registration_data.dart deleted file mode 100644 index 2e92854..0000000 --- a/frontend/lib/models/nanny_registration_data.dart +++ /dev/null @@ -1,136 +0,0 @@ -import 'package:flutter/foundation.dart'; - -class NannyRegistrationData extends ChangeNotifier { - // Step 1: Identity Info - String firstName = ''; - String lastName = ''; - String streetAddress = ''; // Nouveau pour N° et Rue - String postalCode = ''; // Nouveau - String city = ''; // Nouveau - String phone = ''; - String email = ''; - String password = ''; - // String? photoPath; // Déplacé ou géré à l'étape 2 - // bool photoConsent = false; // Déplacé ou géré à l'étape 2 - - // Step 2: Professional Info - String? photoPath; // Ajouté pour l'étape 2 - bool photoConsent = false; // Ajouté pour l'étape 2 - DateTime? dateOfBirth; - String birthCity = ''; // Nouveau - String birthCountry = ''; // Nouveau - // String placeOfBirth = ''; // Remplacé par birthCity et birthCountry - String nir = ''; // Numéro de Sécurité Sociale - String agrementNumber = ''; // Numéro d'agrément - int? capacity; // Number of children the nanny can look after - - // Step 3: Presentation & CGU - String presentationText = ''; - bool cguAccepted = false; - - // --- Methods to update data and notify listeners --- - - void updateIdentityInfo({ - String? firstName, - String? lastName, - String? streetAddress, // Modifié - String? postalCode, // Nouveau - String? city, // Nouveau - String? phone, - String? email, - String? password, - }) { - this.firstName = firstName ?? this.firstName; - this.lastName = lastName ?? this.lastName; - this.streetAddress = streetAddress ?? this.streetAddress; // Modifié - this.postalCode = postalCode ?? this.postalCode; // Nouveau - this.city = city ?? this.city; // Nouveau - this.phone = phone ?? this.phone; - this.email = email ?? this.email; - this.password = password ?? this.password; - // if (photoPath != null || this.photoPath != null) { // Supprimé de l'étape 1 - // this.photoPath = photoPath; - // } - // this.photoConsent = photoConsent ?? this.photoConsent; // Supprimé de l'étape 1 - notifyListeners(); - } - - void updateProfessionalInfo({ - String? photoPath, - bool? photoConsent, - DateTime? dateOfBirth, - String? birthCity, // Nouveau - String? birthCountry, // Nouveau - // String? placeOfBirth, // Remplacé - String? nir, - String? agrementNumber, - int? capacity, - }) { - // Allow setting photoPath to null explicitly - if (photoPath != null || this.photoPath != null) { - this.photoPath = photoPath; - } - this.photoConsent = photoConsent ?? this.photoConsent; - this.dateOfBirth = dateOfBirth ?? this.dateOfBirth; - this.birthCity = birthCity ?? this.birthCity; // Nouveau - this.birthCountry = birthCountry ?? this.birthCountry; // Nouveau - // this.placeOfBirth = placeOfBirth ?? this.placeOfBirth; // Remplacé - this.nir = nir ?? this.nir; - this.agrementNumber = agrementNumber ?? this.agrementNumber; - this.capacity = capacity ?? this.capacity; - notifyListeners(); - } - - void updatePresentationAndCgu({ - String? presentationText, - bool? cguAccepted, - }) { - this.presentationText = presentationText ?? this.presentationText; - this.cguAccepted = cguAccepted ?? this.cguAccepted; - notifyListeners(); - } - - // --- Getters for validation or display --- - bool get isStep1Complete => - firstName.isNotEmpty && - lastName.isNotEmpty && - streetAddress.isNotEmpty && // Modifié - postalCode.isNotEmpty && // Nouveau - city.isNotEmpty && // Nouveau - phone.isNotEmpty && - email.isNotEmpty && - password.isNotEmpty; - - bool get isStep2Complete => - // photoConsent is mandatory if a photo is system-required, otherwise optional. - // For now, let's assume if photoPath is present, consent should ideally be true. - // Or, make consent always mandatory if photo section exists. - // Based on new mockup, photo is present, so consent might be implicitly or explicitly needed. - (photoPath != null ? photoConsent == true : true) && // Ajuster selon la logique de consentement désirée - dateOfBirth != null && - birthCity.isNotEmpty && - birthCountry.isNotEmpty && - nir.isNotEmpty && // Basic check, could add validation - agrementNumber.isNotEmpty && - capacity != null && capacity! > 0; - - bool get isStep3Complete => - // presentationText is optional as per CDC (message au gestionnaire) - cguAccepted; - - bool get isRegistrationComplete => - isStep1Complete && isStep2Complete && isStep3Complete; - - @override - String toString() { - return 'NannyRegistrationData(' - 'firstName: $firstName, lastName: $lastName, ' - 'streetAddress: $streetAddress, postalCode: $postalCode, city: $city, ' - 'phone: $phone, email: $email, ' - // 'photoPath: $photoPath, photoConsent: $photoConsent, ' // Commenté car déplacé/modifié - 'dateOfBirth: $dateOfBirth, birthCity: $birthCity, birthCountry: $birthCountry, ' - 'nir: $nir, agrementNumber: $agrementNumber, capacity: $capacity, ' - 'photoPath (step2): $photoPath, photoConsent (step2): $photoConsent, ' - 'presentationText: $presentationText, cguAccepted: $cguAccepted)'; - } -} \ No newline at end of file diff --git a/frontend/lib/models/user.dart b/frontend/lib/models/user.dart index 8091919..29712ac 100644 --- a/frontend/lib/models/user.dart +++ b/frontend/lib/models/user.dart @@ -20,8 +20,12 @@ class AppUser { id: json['id'] as String, email: json['email'] as String, role: json['role'] as String, - createdAt: DateTime.parse(json['createdAt'] as String), - updatedAt: DateTime.parse(json['updatedAt'] as String), + createdAt: json['createdAt'] != null + ? DateTime.parse(json['createdAt'] as String) + : DateTime.now(), + updatedAt: json['updatedAt'] != null + ? DateTime.parse(json['updatedAt'] as String) + : DateTime.now(), changementMdpObligatoire: json['changement_mdp_obligatoire'] as bool? ?? false, ); } diff --git a/frontend/lib/screens/auth/login_screen.dart b/frontend/lib/screens/auth/login_screen.dart index 6d6cfd2..b441062 100644 --- a/frontend/lib/screens/auth/login_screen.dart +++ b/frontend/lib/screens/auth/login_screen.dart @@ -116,21 +116,23 @@ class _LoginPageState extends State with WidgetsBindingObserver { } } - /// Redirige l'utilisateur selon son rôle + /// Redirige l'utilisateur selon son rôle (GoRouter : context.go). void _redirectUserByRole(String role) { + setState(() => _isLoading = false); switch (role.toLowerCase()) { case 'super_admin': + case 'administrateur': case 'gestionnaire': - Navigator.pushReplacementNamed(context, '/admin-dashboard'); + context.go('/admin-dashboard'); break; case 'parent': - Navigator.pushReplacementNamed(context, '/parent-dashboard'); + context.go('/parent-dashboard'); break; case 'assistante_maternelle': - Navigator.pushReplacementNamed(context, '/am-dashboard'); + context.go('/am-dashboard'); break; default: - Navigator.pushReplacementNamed(context, '/home'); + context.go('/home'); } } diff --git a/frontend/lib/screens/auth/nanny_register_confirmation_screen.dart b/frontend/lib/screens/auth/nanny_register_confirmation_screen.dart deleted file mode 100644 index fbad99b..0000000 --- a/frontend/lib/screens/auth/nanny_register_confirmation_screen.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; - -class NannyRegisterConfirmationScreen extends StatelessWidget { - const NannyRegisterConfirmationScreen({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Inscription Soumise'), - automaticallyImplyLeading: false, // Remove back button - ), - body: Center( - child: Padding( - padding: const EdgeInsets.all(20.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon(Icons.check_circle_outline, color: Colors.green, size: 80), - const SizedBox(height: 20), - const Text( - 'Votre demande d\'inscription a été soumise avec succès !', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), - textAlign: TextAlign.center, - ), - const SizedBox(height: 15), - const Text( - 'Votre compte est en attente de validation par un gestionnaire. Vous recevrez une notification par e-mail une fois votre compte activé.', - textAlign: TextAlign.center, - ), - const SizedBox(height: 30), - ElevatedButton( - onPressed: () { - // Navigate back to the login screen - context.go('/login'); - }, - child: const Text('Retour à la connexion'), - ), - ], - ), - ), - ), - ); - } -} \ No newline at end of file diff --git a/frontend/lib/services/auth_service.dart b/frontend/lib/services/auth_service.dart index 0acaefb..7a44678 100644 --- a/frontend/lib/services/auth_service.dart +++ b/frontend/lib/services/auth_service.dart @@ -23,13 +23,15 @@ class AuthService { if (response.statusCode == 200 || response.statusCode == 201) { final data = jsonDecode(response.body); - - // Stocker les tokens - await TokenService.saveToken(data['accessToken']); - await TokenService.saveRefreshToken(data['refreshToken']); - - // Récupérer le profil utilisateur pour avoir toutes les infos - final user = await _fetchUserProfile(data['accessToken']); + // API renvoie access_token / refresh_token (snake_case) + final accessToken = data['access_token'] as String? ?? data['accessToken'] as String?; + final refreshToken = data['refresh_token'] as String? ?? data['refreshToken'] as String?; + if (accessToken == null) throw Exception('Token absent dans la réponse serveur'); + + await TokenService.saveToken(accessToken); + await TokenService.saveRefreshToken(refreshToken ?? ''); + + final user = await _fetchUserProfile(accessToken); // Stocker l'utilisateur en cache await _saveCurrentUser(user); @@ -80,8 +82,9 @@ class AuthService { Uri.parse('${ApiConfig.baseUrl}${ApiConfig.changePasswordRequired}'), headers: ApiConfig.authHeaders(token), body: jsonEncode({ - 'currentPassword': currentPassword, - 'newPassword': newPassword, + 'mot_de_passe_actuel': currentPassword, + 'nouveau_mot_de_passe': newPassword, + 'confirmation_mot_de_passe': newPassword, }), ); diff --git a/frontend/lib/widgets/choice_card_widget.dart b/frontend/lib/widgets/choice_card_widget.dart index ecb418e..1639141 100644 --- a/frontend/lib/widgets/choice_card_widget.dart +++ b/frontend/lib/widgets/choice_card_widget.dart @@ -55,8 +55,14 @@ class ChoiceCardWidget extends StatelessWidget { required bool isMobile, }) { final Color baseRoseColor = Colors.pink.shade300; - final Color initialShadow = baseRoseColor.withAlpha(90); - final Color hoverShadow = baseRoseColor.withAlpha(130); + final Color initialShadow = isMobile + ? Colors.black.withOpacity(0.45) + : baseRoseColor.withAlpha(90); + final Color hoverShadow = isMobile + ? Colors.black.withOpacity(0.5) + : baseRoseColor.withAlpha(130); + final double initialElevation = isMobile ? 14.0 : 4.0; + final double hoverElevation = isMobile ? 18.0 : 8.0; return Column( mainAxisSize: MainAxisSize.min, @@ -64,6 +70,8 @@ class ChoiceCardWidget extends StatelessWidget { HoverReliefWidget( onPressed: onPressed, borderRadius: BorderRadius.circular(15.0), + initialElevation: initialElevation, + hoverElevation: hoverElevation, initialShadowColor: initialShadow, hoverShadowColor: hoverShadow, child: Padding( diff --git a/scripts/gitea-close-issue.sh b/scripts/gitea-close-issue.sh new file mode 100644 index 0000000..3403745 --- /dev/null +++ b/scripts/gitea-close-issue.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# Ferme une issue Gitea via l'API. +# Usage: GITEA_TOKEN=votre_token ./scripts/gitea-close-issue.sh [numéro] +# Exemple: GITEA_TOKEN=xxx ./scripts/gitea-close-issue.sh 83 + +set -e +ISSUE="${1:-83}" +BASE_URL="${GITEA_URL:-https://git.ptits-pas.fr/api/v1}" +REPO="jmartin/petitspas" + +if [ -z "$GITEA_TOKEN" ]; then + if [ -f .gitea-token ]; then + GITEA_TOKEN=$(cat .gitea-token) + fi +fi + +if [ -z "$GITEA_TOKEN" ]; then + echo "Définir GITEA_TOKEN ou créer .gitea-token avec votre token Gitea." + exit 1 +fi + +echo "Fermeture de l'issue #$ISSUE..." +RESP=$(curl -s -w "\n%{http_code}" -X PATCH \ + -H "Authorization: token $GITEA_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"state":"closed"}' \ + "$BASE_URL/repos/$REPO/issues/$ISSUE") +HTTP_CODE=$(echo "$RESP" | tail -1) +BODY=$(echo "$RESP" | sed '$d') + +if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "201" ]; then + echo "Issue #$ISSUE fermée." +else + echo "Erreur HTTP $HTTP_CODE: $BODY" + exit 1 +fi