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:
@@ -0,0 +1,96 @@
|
||||
import 'dart:io';
|
||||
|
||||
class ChildminderId {
|
||||
String firstName;
|
||||
String lastName;
|
||||
String address;
|
||||
String postalCode;
|
||||
String city;
|
||||
String phone;
|
||||
String email;
|
||||
String password;
|
||||
File? profilePicture;
|
||||
bool photoConsent;
|
||||
|
||||
ChildminderId({
|
||||
this.firstName = '',
|
||||
this.lastName = '',
|
||||
this.address = '',
|
||||
this.postalCode = '',
|
||||
this.city = '',
|
||||
this.phone = '',
|
||||
this.email = '',
|
||||
this.password = '',
|
||||
this.profilePicture,
|
||||
this.photoConsent = false,
|
||||
});
|
||||
}
|
||||
|
||||
class ChildminderProfessional {
|
||||
String dateOfBirth;
|
||||
String birthCity;
|
||||
String birthCountry;
|
||||
String socialSecurityNumber; // NIR
|
||||
String agreementNumber;
|
||||
int maxChildren;
|
||||
|
||||
ChildminderProfessional({
|
||||
this.dateOfBirth = '',
|
||||
this.birthCity = '',
|
||||
this.birthCountry = '',
|
||||
this.socialSecurityNumber = '',
|
||||
this.agreementNumber = '',
|
||||
this.maxChildren = 1,
|
||||
});
|
||||
}
|
||||
|
||||
class ChildminderRegistrationData {
|
||||
ChildminderId identity;
|
||||
ChildminderProfessional professional;
|
||||
String presentationMessage;
|
||||
bool cguAccepted;
|
||||
bool isPhotoRequired;
|
||||
|
||||
ChildminderRegistrationData({
|
||||
ChildminderId? identityData,
|
||||
ChildminderProfessional? professionalData,
|
||||
this.presentationMessage = '',
|
||||
this.cguAccepted = false,
|
||||
this.isPhotoRequired = false,
|
||||
}) : identity = identityData ?? ChildminderId(),
|
||||
professional = professionalData ?? ChildminderProfessional();
|
||||
|
||||
void updateIdentity(ChildminderId data) {
|
||||
identity = data;
|
||||
}
|
||||
|
||||
void updateProfessional(ChildminderProfessional data) {
|
||||
professional = data;
|
||||
}
|
||||
|
||||
void updatePresentation(String message) {
|
||||
presentationMessage = message;
|
||||
}
|
||||
|
||||
void acceptCGU() {
|
||||
cguAccepted = true;
|
||||
}
|
||||
|
||||
bool get isComplete {
|
||||
return identity.firstName.isNotEmpty &&
|
||||
identity.lastName.isNotEmpty &&
|
||||
identity.address.isNotEmpty &&
|
||||
identity.postalCode.isNotEmpty &&
|
||||
identity.city.isNotEmpty &&
|
||||
identity.phone.isNotEmpty &&
|
||||
identity.email.isNotEmpty &&
|
||||
identity.password.isNotEmpty &&
|
||||
professional.dateOfBirth.isNotEmpty &&
|
||||
professional.birthCity.isNotEmpty &&
|
||||
professional.birthCountry.isNotEmpty &&
|
||||
professional.socialSecurityNumber.isNotEmpty &&
|
||||
professional.agreementNumber.isNotEmpty &&
|
||||
cguAccepted &&
|
||||
(!isPhotoRequired || (identity.profilePicture != null && identity.photoConsent));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
class AssistantModel {
|
||||
final String id;
|
||||
final String firstName;
|
||||
final String lastName;
|
||||
final String? photoUrl;
|
||||
final double hourlyRate;
|
||||
final double dailyFees;
|
||||
final AssistantStatus status;
|
||||
final String? address;
|
||||
final String? phone;
|
||||
final String? email;
|
||||
|
||||
AssistantModel({
|
||||
required this.id,
|
||||
required this.firstName,
|
||||
required this.lastName,
|
||||
this.photoUrl,
|
||||
required this.hourlyRate,
|
||||
required this.dailyFees,
|
||||
required this.status,
|
||||
this.address,
|
||||
this.phone,
|
||||
this.email,
|
||||
});
|
||||
|
||||
factory AssistantModel.fromJson(Map<String, dynamic> json) {
|
||||
return AssistantModel(
|
||||
id: json['id'],
|
||||
firstName: json['firstName'],
|
||||
lastName: json['lastName'],
|
||||
photoUrl: json['photoUrl'],
|
||||
hourlyRate: json['hourlyRate'].toDouble(),
|
||||
dailyFees: json['dailyFees'].toDouble(),
|
||||
status: AssistantStatus.values.byName(json['status']),
|
||||
address: json['address'],
|
||||
phone: json['phone'],
|
||||
email: json['email'],
|
||||
);
|
||||
}
|
||||
|
||||
String get fullName => '$firstName $lastName';
|
||||
String get hourlyRateFormatted => '${hourlyRate.toStringAsFixed(2)} €/h';
|
||||
String get dailyFeesFormatted => '${dailyFees.toStringAsFixed(2)} €/jour';
|
||||
}
|
||||
|
||||
enum AssistantStatus {
|
||||
available,
|
||||
busy,
|
||||
onHoliday,
|
||||
unavailable,
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
class ChildModel {
|
||||
final String id;
|
||||
final String firstName;
|
||||
final String? lastName;
|
||||
final String? photoUrl;
|
||||
final DateTime birthDate;
|
||||
final ChildStatus status;
|
||||
final String? assistantId;
|
||||
|
||||
ChildModel({
|
||||
required this.id,
|
||||
required this.firstName,
|
||||
this.lastName,
|
||||
this.photoUrl,
|
||||
required this.birthDate,
|
||||
required this.status,
|
||||
this.assistantId,
|
||||
});
|
||||
|
||||
factory ChildModel.fromJson(Map<String, dynamic> json) {
|
||||
return ChildModel(
|
||||
id: json['id'],
|
||||
firstName: json['firstName'],
|
||||
lastName: json['lastName'],
|
||||
photoUrl: json['photoUrl'],
|
||||
birthDate: DateTime.parse(json['birthDate']),
|
||||
status: ChildStatus.values.byName(json['status']),
|
||||
assistantId: json['assistantId'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'firstName': firstName,
|
||||
'lastName': lastName,
|
||||
'photoUrl': photoUrl,
|
||||
'birthDate': birthDate.toIso8601String(),
|
||||
'status': status.name,
|
||||
'assistantId': assistantId,
|
||||
};
|
||||
}
|
||||
|
||||
String get fullName => lastName != null ? '$firstName $lastName' : firstName;
|
||||
|
||||
int get ageInMonths {
|
||||
final now = DateTime.now();
|
||||
return (now.year - birthDate.year) * 12 + (now.month - birthDate.month);
|
||||
}
|
||||
}
|
||||
|
||||
enum ChildStatus {
|
||||
withAssistant, // En garde chez l'assistante
|
||||
available, // Disponible
|
||||
onHoliday, // En vacances
|
||||
sick, // Malade
|
||||
searching, // Recherche d'assistante
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
class ContractModel {
|
||||
final String id;
|
||||
final String childId;
|
||||
final String assistantId;
|
||||
final ContractStatus status;
|
||||
final DateTime startDate;
|
||||
final DateTime? endDate;
|
||||
final double hourlyRate;
|
||||
final Map<String, dynamic>? terms;
|
||||
final DateTime createdAt;
|
||||
final DateTime? signedAt;
|
||||
|
||||
ContractModel({
|
||||
required this.id,
|
||||
required this.childId,
|
||||
required this.assistantId,
|
||||
required this.status,
|
||||
required this.startDate,
|
||||
this.endDate,
|
||||
required this.hourlyRate,
|
||||
this.terms,
|
||||
required this.createdAt,
|
||||
this.signedAt,
|
||||
});
|
||||
|
||||
factory ContractModel.fromJson(Map<String, dynamic> json) {
|
||||
return ContractModel(
|
||||
id: json['id'],
|
||||
childId: json['childId'],
|
||||
assistantId: json['assistantId'],
|
||||
status: ContractStatus.values.byName(json['status']),
|
||||
startDate: DateTime.parse(json['startDate']),
|
||||
endDate: json['endDate'] != null ? DateTime.parse(json['endDate']) : null,
|
||||
hourlyRate: json['hourlyRate'].toDouble(),
|
||||
terms: json['terms'],
|
||||
createdAt: DateTime.parse(json['createdAt']),
|
||||
signedAt: json['signedAt'] != null ? DateTime.parse(json['signedAt']) : null,
|
||||
);
|
||||
}
|
||||
|
||||
bool get isActive => status == ContractStatus.active;
|
||||
bool get needsSignature => status == ContractStatus.draft;
|
||||
String get statusLabel {
|
||||
switch (status) {
|
||||
case ContractStatus.draft:
|
||||
return 'Brouillon';
|
||||
case ContractStatus.pending:
|
||||
return 'En attente de validation';
|
||||
case ContractStatus.active:
|
||||
return 'En cours';
|
||||
case ContractStatus.ended:
|
||||
return 'Terminé';
|
||||
case ContractStatus.cancelled:
|
||||
return 'Annulé';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum ContractStatus {
|
||||
draft,
|
||||
pending,
|
||||
active,
|
||||
ended,
|
||||
cancelled,
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
class ConversationModel {
|
||||
final String id;
|
||||
final String title;
|
||||
final List<String> participantIds;
|
||||
final List<MessageModel> messages;
|
||||
final DateTime lastMessageAt;
|
||||
final int unreadCount;
|
||||
final String? childId;
|
||||
|
||||
ConversationModel({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.participantIds,
|
||||
required this.messages,
|
||||
required this.lastMessageAt,
|
||||
this.unreadCount = 0,
|
||||
this.childId,
|
||||
});
|
||||
|
||||
MessageModel? get lastMessage => messages.isNotEmpty ? messages.last : null;
|
||||
bool get hasUnreadMessages => unreadCount > 0;
|
||||
}
|
||||
|
||||
class MessageModel {
|
||||
final String id;
|
||||
final String content;
|
||||
final String senderId;
|
||||
final DateTime sentAt;
|
||||
final bool isFromAI;
|
||||
final MessageStatus status;
|
||||
|
||||
MessageModel({
|
||||
required this.id,
|
||||
required this.content,
|
||||
required this.senderId,
|
||||
required this.sentAt,
|
||||
this.isFromAI = false,
|
||||
required this.status,
|
||||
});
|
||||
}
|
||||
|
||||
enum MessageStatus {
|
||||
sent,
|
||||
delivered,
|
||||
read,
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
class EventModel {
|
||||
final String id;
|
||||
final String title;
|
||||
final String? description;
|
||||
final DateTime startDate;
|
||||
final DateTime? endDate;
|
||||
final EventType type;
|
||||
final EventStatus status;
|
||||
final String? childId;
|
||||
final String? assistantId;
|
||||
final String? createdBy;
|
||||
|
||||
EventModel({
|
||||
required this.id,
|
||||
required this.title,
|
||||
this.description,
|
||||
required this.startDate,
|
||||
this.endDate,
|
||||
required this.type,
|
||||
required this.status,
|
||||
this.childId,
|
||||
this.assistantId,
|
||||
this.createdBy,
|
||||
});
|
||||
|
||||
factory EventModel.fromJson(Map<String, dynamic> json) {
|
||||
return EventModel(
|
||||
id: json['id'],
|
||||
title: json['title'],
|
||||
description: json['description'],
|
||||
startDate: DateTime.parse(json['startDate']),
|
||||
endDate: json['endDate'] != null ? DateTime.parse(json['endDate']) : null,
|
||||
type: EventType.values.byName(json['type']),
|
||||
status: EventStatus.values.byName(json['status']),
|
||||
childId: json['childId'],
|
||||
assistantId: json['assistantId'],
|
||||
createdBy: json['createdBy'],
|
||||
);
|
||||
}
|
||||
|
||||
bool get isMultiDay => endDate != null && !isSameDay(startDate, endDate!);
|
||||
bool get isPending => status == EventStatus.pending;
|
||||
bool get needsConfirmation => isPending && createdBy != 'current_user';
|
||||
|
||||
static bool isSameDay(DateTime date1, DateTime date2) {
|
||||
return date1.year == date2.year &&
|
||||
date1.month == date2.month &&
|
||||
date1.day == date2.day;
|
||||
}
|
||||
}
|
||||
|
||||
enum EventType {
|
||||
parentVacation, // Vacances parents
|
||||
childAbsence, // Absence enfant
|
||||
rpeActivity, // Activité RPE
|
||||
assistantVacation, // Congés assistante maternelle
|
||||
sickLeave, // Arrêt maladie
|
||||
personalNote, // Note personnelle
|
||||
}
|
||||
|
||||
enum EventStatus {
|
||||
confirmed,
|
||||
pending,
|
||||
refused,
|
||||
cancelled,
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
class NotificationModel {
|
||||
final String id;
|
||||
final String title;
|
||||
final String content;
|
||||
final NotificationType type;
|
||||
final DateTime createdAt;
|
||||
final bool isRead;
|
||||
final String? actionUrl;
|
||||
final Map<String, dynamic>? metadata;
|
||||
|
||||
NotificationModel({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.content,
|
||||
required this.type,
|
||||
required this.createdAt,
|
||||
this.isRead = false,
|
||||
this.actionUrl,
|
||||
this.metadata,
|
||||
});
|
||||
|
||||
factory NotificationModel.fromJson(Map<String, dynamic> json) {
|
||||
return NotificationModel(
|
||||
id: json['id'],
|
||||
title: json['title'],
|
||||
content: json['content'],
|
||||
type: NotificationType.values.byName(json['type']),
|
||||
createdAt: DateTime.parse(json['createdAt']),
|
||||
isRead: json['isRead'] ?? false,
|
||||
actionUrl: json['actionUrl'],
|
||||
metadata: json['metadata'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum NotificationType {
|
||||
newEvent, // Nouvel événement
|
||||
fileModified, // Dossier modifié
|
||||
contractPending, // Contrat en attente
|
||||
paymentPending, // Paiement en attente
|
||||
unreadMessage, // Message non lu
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
import 'dart:io'; // Pour File
|
||||
import '../models/card_assets.dart'; // Import de l'enum CardColorVertical
|
||||
|
||||
class ParentData {
|
||||
String firstName;
|
||||
String lastName;
|
||||
String address; // Rue et numéro
|
||||
String postalCode; // Ajout
|
||||
String city; // Ajout
|
||||
String phone;
|
||||
String email;
|
||||
String password; // Peut-être pas nécessaire pour le récap, mais pour la création initiale si
|
||||
File? profilePicture; // Chemin ou objet File
|
||||
|
||||
ParentData({
|
||||
this.firstName = '',
|
||||
this.lastName = '',
|
||||
this.address = '', // Rue
|
||||
this.postalCode = '', // Ajout
|
||||
this.city = '', // Ajout
|
||||
this.phone = '',
|
||||
this.email = '',
|
||||
this.password = '',
|
||||
this.profilePicture,
|
||||
});
|
||||
}
|
||||
|
||||
class ChildData {
|
||||
String firstName;
|
||||
String lastName;
|
||||
String dob; // Date de naissance ou prévisionnelle
|
||||
bool photoConsent;
|
||||
bool multipleBirth;
|
||||
bool isUnbornChild;
|
||||
File? imageFile;
|
||||
CardColorVertical cardColor; // Nouveau champ pour la couleur de la carte
|
||||
|
||||
ChildData({
|
||||
this.firstName = '',
|
||||
this.lastName = '',
|
||||
this.dob = '',
|
||||
this.photoConsent = false,
|
||||
this.multipleBirth = false,
|
||||
this.isUnbornChild = false,
|
||||
this.imageFile,
|
||||
required this.cardColor, // Rendre requis dans le constructeur
|
||||
});
|
||||
}
|
||||
|
||||
class UserRegistrationData {
|
||||
ParentData parent1;
|
||||
ParentData? parent2; // Optionnel
|
||||
List<ChildData> children;
|
||||
String motivationText;
|
||||
bool cguAccepted;
|
||||
|
||||
UserRegistrationData({
|
||||
ParentData? parent1Data,
|
||||
this.parent2,
|
||||
List<ChildData>? childrenData,
|
||||
this.motivationText = '',
|
||||
this.cguAccepted = false,
|
||||
}) : parent1 = parent1Data ?? ParentData(),
|
||||
children = childrenData ?? [];
|
||||
|
||||
// Méthode pour ajouter/mettre à jour le parent 1
|
||||
void updateParent1(ParentData data) {
|
||||
parent1 = data;
|
||||
}
|
||||
|
||||
// Méthode pour ajouter/mettre à jour le parent 2
|
||||
void updateParent2(ParentData? data) {
|
||||
parent2 = data;
|
||||
}
|
||||
|
||||
// Méthode pour ajouter un enfant
|
||||
void addChild(ChildData child) {
|
||||
children.add(child);
|
||||
}
|
||||
|
||||
// Méthode pour mettre à jour un enfant (si nécessaire plus tard)
|
||||
void updateChild(int index, ChildData child) {
|
||||
if (index >= 0 && index < children.length) {
|
||||
children[index] = child;
|
||||
}
|
||||
}
|
||||
|
||||
// Mettre à jour la motivation
|
||||
void updateMotivation(String text) {
|
||||
motivationText = text;
|
||||
}
|
||||
|
||||
// Accepter les CGU
|
||||
void acceptCGU() {
|
||||
cguAccepted = true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user