Merge master into develop - Synchronisation des branches

Fusion des travaux :
- Backend complet (ConfigService, DocumentsLegaux, Auth, etc.)
- Frontend étapes inscription 1-2
- Infrastructure Docker
- Documentation technique

Résolution des conflits :
- Images déplacées vers frontend/assets/images/
- Dossier Archives supprimé
- Backend : version master conservée
- Frontend : améliorations UI de develop conservées
This commit is contained in:
2026-01-27 14:56:49 +01:00
249 changed files with 33816 additions and 1449 deletions
+32
View File
@@ -0,0 +1,32 @@
class ApiConfig {
// static const String baseUrl = 'http://localhost:3000/api/v1/';
static const String baseUrl = 'https://ynov.ptits-pas.fr/api/v1';
// Auth endpoints
static const String login = '/auth/login';
static const String register = '/auth/register';
static const String refreshToken = '/auth/refresh';
// Users endpoints
static const String users = '/users';
static const String userProfile = '/users/profile';
static const String userChildren = '/users/children';
// Dashboard endpoints
static const String dashboard = '/dashboard';
static const String events = '/events';
static const String contracts = '/contracts';
static const String conversations = '/conversations';
static const String notifications = '/notifications';
// Headers
static Map<String, String> get headers => {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
static Map<String, String> authHeaders(String token) => {
...headers,
'Authorization': 'Bearer $token',
};
}
@@ -0,0 +1,71 @@
import 'package:shared_preferences/shared_preferences.dart';
class TokenService {
// static const _storage = FlutterSecureStorage();
static const _tokenKey = 'access_token';
static const String _refreshTokenKey = 'refresh_token';
static const _roleKey = 'user_role';
// Stockage du token
static Future<void> saveToken(String token) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_tokenKey, token);
}
// Stockage du refresh token
static Future<void> saveRefreshToken(String refreshToken) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_refreshTokenKey, refreshToken);
}
// Stockage du rôle
static Future<void> saveRole(String role) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_roleKey, role);
}
// Récupération du token
static Future<String?> getToken() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString(_tokenKey);
}
// Récupération du refresh token
static Future<String?> getRefreshToken() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString(_refreshTokenKey);
}
// Récupération du rôle
static Future<String?> getRole() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString(_roleKey);
}
// Suppression du token
static Future<void> deleteToken() async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_tokenKey);
}
// Suppression du refresh token
static Future<void> deleteRefreshToken() async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_refreshTokenKey);
}
// Suppression du rôle
static Future<void> deleteRole() async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_roleKey);
}
// Nettoyage complet
static Future<void> clearAll() async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_tokenKey);
await prefs.remove(_refreshTokenKey);
await prefs.remove(_roleKey);
}
}
+202
View File
@@ -0,0 +1,202 @@
import 'package:p_tits_pas/models/m_dashbord/assistant_model.dart';
import 'package:p_tits_pas/models/m_dashbord/child_model.dart';
import 'package:p_tits_pas/models/m_dashbord/contract_model.dart';
import 'package:p_tits_pas/models/m_dashbord/conversation_model.dart';
import 'package:p_tits_pas/models/m_dashbord/event_model.dart';
import 'package:p_tits_pas/models/m_dashbord/notification_model.dart';
class DashboardService {
// URL de base de l'API
static const String _baseUrl = 'YOUR_API_BASE_URL';
// Récupérer la liste des enfants
Future<List<ChildModel>> getChildren() async {
try {
// TODO: Implémenter l'appel API
// Exemple de mock data pour le développement
return [
ChildModel(
id: '1',
firstName: 'Emma',
birthDate: DateTime(2020, 5, 15),
photoUrl: 'assets/images/child1.jpg',
status: ChildStatus.onHoliday,
),
ChildModel(
id: '2',
firstName: 'Lucas',
birthDate: DateTime(2021, 3, 10),
photoUrl: 'assets/images/child2.jpg',
status: ChildStatus.searching,
),
];
} catch (e) {
throw Exception('Erreur lors de la récupération des enfants: $e');
}
}
// Récupérer l'assistante maternelle pour un enfant
Future<AssistantModel> getAssistantForChild(String childId) async {
try {
// TODO: Implémenter l'appel API
return AssistantModel(
id: 'am1',
firstName: 'Marie',
lastName: 'Dupont',
hourlyRate: 10.0,
dailyFees: 80.0,
status: AssistantStatus.available,
photoUrl: 'assets/images/assistant1.jpg',
address: '123 rue des Lilas',
phone: '0123456789',
);
} catch (e) {
throw Exception('Erreur lors de la récupération de l\'assistante: $e');
}
}
// Récupérer les événements pour un enfant
Future<List<EventModel>> getEventsForChild(String childId) async {
try {
// TODO: Implémenter l'appel API
return [
EventModel(
id: 'evt1',
title: 'Rendez-vous médical',
startDate: DateTime.now().add(const Duration(days: 2)),
type: EventType.parentVacation,
status: EventStatus.pending,
description: 'Visite de routine',
childId: childId,
),
];
} catch (e) {
throw Exception('Erreur lors de la récupération des événements: $e');
}
}
// Récupérer tous les événements à venir
Future<List<EventModel>> getUpcomingEvents() async {
try {
// TODO: Implémenter l'appel API
return [
EventModel(
id: 'evt1',
title: 'Activité peinture',
startDate: DateTime.now().add(const Duration(days: 1)),
endDate: DateTime.now().add(const Duration(days: 1, hours: 2)),
type: EventType.parentVacation,
status: EventStatus.pending,
description: 'Atelier créatif',
childId: '1',
),
];
} catch (e) {
throw Exception('Erreur lors de la récupération des événements: $e');
}
}
// Récupérer les contrats
Future<List<ContractModel>> getContracts() async {
try {
// TODO: Implémenter l'appel API
return [
ContractModel(
id: 'contract1',
childId: '1',
assistantId: 'am1',
startDate: DateTime(2023, 9, 1),
endDate: DateTime(2024, 8, 31),
status: ContractStatus.pending,
hourlyRate: 10.0,
createdAt: DateTime.now(),
),
];
} catch (e) {
throw Exception('Erreur lors de la récupération des contrats: $e');
}
}
// Récupérer les contrats pour un enfant spécifique
Future<List<ContractModel>> getContractsForChild(String childId) async {
try {
// TODO: Implémenter l'appel API
return [
ContractModel(
id: 'contract1',
childId: childId,
assistantId: 'am1',
startDate: DateTime(2023, 9, 1),
endDate: DateTime(2024, 8, 31),
status: ContractStatus.active,
hourlyRate: 10.0,
createdAt: DateTime.now(),
),
];
} catch (e) {
throw Exception('Erreur lors de la récupération des contrats: $e');
}
}
// Récupérer les conversations
Future<List<ConversationModel>> getConversations() async {
try {
// TODO: Implémenter l'appel API
return [
ConversationModel(
id: 'conv1',
title: 'Conversation avec Marie Dupont',
participantIds: ['am1'],
messages: [
MessageModel(
id: 'msg1',
content: 'Bonjour, comment ça va ?',
senderId: 'am1',
sentAt: DateTime.now().subtract(const Duration(hours: 2)),
status: MessageStatus.read,
),
MessageModel(
id: 'msg2',
content: 'Tout va bien, merci !',
senderId: 'parent1',
sentAt: DateTime.now().subtract(const Duration(hours: 1, minutes: 30)),
status: MessageStatus.read,
),
],
lastMessageAt: DateTime.now().subtract(const Duration(hours: 2)),
unreadCount: 2,
),
];
} catch (e) {
throw Exception('Erreur lors de la récupération des conversations: $e');
}
}
// Récupérer les notifications
Future<List<NotificationModel>> getNotifications() async {
try {
// TODO: Implémenter l'appel API
return [
NotificationModel(
id: 'notif1',
title: 'Nouveau message',
createdAt: DateTime.now(),
isRead: false,
type: NotificationType.contractPending,
content: 'Votre contrat est en attente',
),
];
} catch (e) {
throw Exception('Erreur lors de la récupération des notifications: $e');
}
}
// Marquer une notification comme lue
Future<void> markNotificationAsRead(String notificationId) async {
try {
// TODO: Implémenter l'appel API
} catch (e) {
throw Exception('Erreur lors du marquage de la notification: $e');
}
}
}
@@ -0,0 +1,20 @@
import 'package:flutter/cupertino.dart';
class NavigationService {
static void handleLoginSuccess(BuildContext context, String role) {
switch (role) {
case 'admin':
Navigator.pushReplacementNamed(context, '/admin_dashboard');
break;
case 'gestionnaire':
Navigator.pushReplacementNamed(context, '/gestionnaire_dashboard');
break;
case 'parent':
Navigator.pushReplacementNamed(context, '/parent-dashboard');
break;
case 'assistante_maternelle':
Navigator.pushReplacementNamed(context, '/assistante_maternelle_dashboard');
break;
}
}
}