371 lines
12 KiB
Dart
371 lines
12 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:geosector_app/core/data/models/user_model.dart';
|
|
import 'custom_text_field.dart';
|
|
|
|
class UserForm extends StatefulWidget {
|
|
final UserModel? user;
|
|
final Function(UserModel)? onSubmit;
|
|
final bool readOnly;
|
|
|
|
const UserForm({
|
|
Key? key,
|
|
this.user,
|
|
this.onSubmit,
|
|
this.readOnly = false,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
State<UserForm> createState() => _UserFormState();
|
|
}
|
|
|
|
class _UserFormState extends State<UserForm> {
|
|
final _formKey = GlobalKey<FormState>();
|
|
|
|
// Controllers
|
|
late final TextEditingController _usernameController;
|
|
late final TextEditingController _firstNameController;
|
|
late final TextEditingController _nameController;
|
|
late final TextEditingController _phoneController;
|
|
late final TextEditingController _mobileController;
|
|
late final TextEditingController _emailController;
|
|
late final TextEditingController _dateNaissanceController;
|
|
late final TextEditingController _dateEmbaucheController;
|
|
|
|
// Form values
|
|
int _fkTitre = 1; // 1 = M., 2 = Mme
|
|
DateTime? _dateNaissance;
|
|
DateTime? _dateEmbauche;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
// Initialize controllers with user data if available
|
|
final user = widget.user;
|
|
_usernameController = TextEditingController(text: user?.username ?? '');
|
|
_firstNameController = TextEditingController(text: user?.firstName ?? '');
|
|
_nameController = TextEditingController(text: user?.name ?? '');
|
|
_phoneController = TextEditingController(text: user?.phone ?? '');
|
|
_mobileController = TextEditingController(text: user?.mobile ?? '');
|
|
_emailController = TextEditingController(text: user?.email ?? '');
|
|
|
|
_dateNaissance = user?.dateNaissance;
|
|
_dateEmbauche = user?.dateEmbauche;
|
|
|
|
_dateNaissanceController = TextEditingController(
|
|
text: _dateNaissance != null
|
|
? DateFormat('dd/MM/yyyy').format(_dateNaissance!)
|
|
: '');
|
|
|
|
_dateEmbaucheController = TextEditingController(
|
|
text: _dateEmbauche != null
|
|
? DateFormat('dd/MM/yyyy').format(_dateEmbauche!)
|
|
: '');
|
|
|
|
_fkTitre = user?.fkTitre ?? 1;
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_usernameController.dispose();
|
|
_firstNameController.dispose();
|
|
_nameController.dispose();
|
|
_phoneController.dispose();
|
|
_mobileController.dispose();
|
|
_emailController.dispose();
|
|
_dateNaissanceController.dispose();
|
|
_dateEmbaucheController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
// Méthode simplifiée pour sélectionner une date
|
|
void _selectDate(BuildContext context, bool isDateNaissance) {
|
|
// Utiliser un bloc try-catch pour capturer toutes les erreurs possibles
|
|
try {
|
|
// Afficher le sélecteur de date sans spécifier de locale
|
|
showDatePicker(
|
|
context: context,
|
|
initialDate: DateTime.now(), // Toujours utiliser la date actuelle
|
|
firstDate: DateTime(1900),
|
|
lastDate: DateTime.now(),
|
|
// Ne pas spécifier de locale pour éviter les problèmes
|
|
).then((DateTime? picked) {
|
|
// Vérifier si une date a été sélectionnée
|
|
if (picked != null) {
|
|
setState(() {
|
|
// Mettre à jour la date et le texte du contrôleur
|
|
if (isDateNaissance) {
|
|
_dateNaissance = picked;
|
|
_dateNaissanceController.text =
|
|
DateFormat('dd/MM/yyyy').format(picked);
|
|
} else {
|
|
_dateEmbauche = picked;
|
|
_dateEmbaucheController.text =
|
|
DateFormat('dd/MM/yyyy').format(picked);
|
|
}
|
|
});
|
|
}
|
|
}).catchError((error) {
|
|
// Gérer les erreurs spécifiques au sélecteur de date
|
|
debugPrint('Erreur lors de la sélection de la date: $error');
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text('Erreur lors de la sélection de la date'),
|
|
backgroundColor: Colors.red,
|
|
),
|
|
);
|
|
});
|
|
} catch (e) {
|
|
// Gérer toutes les autres erreurs
|
|
debugPrint('Exception lors de l\'affichage du sélecteur de date: $e');
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text('Impossible d\'afficher le sélecteur de date'),
|
|
backgroundColor: Colors.red,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
void _submitForm() {
|
|
if (_formKey.currentState!.validate()) {
|
|
final user = widget.user?.copyWith(
|
|
firstName: _firstNameController.text,
|
|
name: _nameController.text,
|
|
phone: _phoneController.text,
|
|
mobile: _mobileController.text,
|
|
email: _emailController.text,
|
|
fkTitre: _fkTitre,
|
|
dateNaissance: _dateNaissance,
|
|
dateEmbauche: _dateEmbauche,
|
|
) ??
|
|
UserModel(
|
|
id: 0, // Sera remplacé par l'API
|
|
firstName: _firstNameController.text,
|
|
name: _nameController.text,
|
|
phone: _phoneController.text,
|
|
mobile: _mobileController.text,
|
|
email: _emailController.text,
|
|
fkTitre: _fkTitre,
|
|
dateNaissance: _dateNaissance,
|
|
dateEmbauche: _dateEmbauche,
|
|
role: 1, // Valeur par défaut
|
|
createdAt: DateTime.now(),
|
|
lastSyncedAt: DateTime.now(),
|
|
);
|
|
|
|
if (widget.onSubmit != null) {
|
|
widget.onSubmit!(user);
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final theme = Theme.of(context);
|
|
|
|
return Form(
|
|
key: _formKey,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Nom d'utilisateur (en lecture seule)
|
|
CustomTextField(
|
|
controller: _usernameController,
|
|
label: "Nom d'utilisateur",
|
|
readOnly: true, // Toujours en lecture seule
|
|
prefixIcon: Icons.account_circle,
|
|
),
|
|
const SizedBox(height: 16),
|
|
|
|
// Titre (M. ou Mme)
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"Titre",
|
|
style: theme.textTheme.titleSmall?.copyWith(
|
|
fontWeight: FontWeight.w500,
|
|
color: theme.colorScheme.onBackground,
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Row(
|
|
children: [
|
|
_buildRadioOption(
|
|
value: 1,
|
|
label: 'M.',
|
|
groupValue: _fkTitre,
|
|
onChanged: widget.readOnly
|
|
? null
|
|
: (value) {
|
|
setState(() {
|
|
_fkTitre = value!;
|
|
});
|
|
},
|
|
),
|
|
const SizedBox(width: 40),
|
|
_buildRadioOption(
|
|
value: 2,
|
|
label: 'Mme',
|
|
groupValue: _fkTitre,
|
|
onChanged: widget.readOnly
|
|
? null
|
|
: (value) {
|
|
setState(() {
|
|
_fkTitre = value!;
|
|
});
|
|
},
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 16),
|
|
|
|
// Prénom
|
|
CustomTextField(
|
|
controller: _firstNameController,
|
|
label: "Prénom",
|
|
readOnly: widget.readOnly,
|
|
validator: (value) {
|
|
if (value == null || value.isEmpty) {
|
|
return "Veuillez entrer le prénom";
|
|
}
|
|
return null;
|
|
},
|
|
),
|
|
const SizedBox(height: 16),
|
|
|
|
// Nom
|
|
CustomTextField(
|
|
controller: _nameController,
|
|
label: "Nom",
|
|
readOnly: widget.readOnly,
|
|
validator: (value) {
|
|
if (value == null || value.isEmpty) {
|
|
return "Veuillez entrer le nom";
|
|
}
|
|
return null;
|
|
},
|
|
),
|
|
const SizedBox(height: 16),
|
|
|
|
// Téléphone fixe
|
|
CustomTextField(
|
|
controller: _phoneController,
|
|
label: "Téléphone fixe",
|
|
keyboardType: TextInputType.phone,
|
|
readOnly: widget.readOnly,
|
|
inputFormatters: [
|
|
FilteringTextInputFormatter.digitsOnly,
|
|
LengthLimitingTextInputFormatter(10),
|
|
],
|
|
validator: (value) {
|
|
if (value != null && value.isNotEmpty && value.length < 10) {
|
|
return "Le numéro de téléphone doit contenir 10 chiffres";
|
|
}
|
|
return null;
|
|
},
|
|
),
|
|
const SizedBox(height: 16),
|
|
|
|
// Téléphone mobile
|
|
CustomTextField(
|
|
controller: _mobileController,
|
|
label: "Téléphone mobile",
|
|
keyboardType: TextInputType.phone,
|
|
readOnly: widget.readOnly,
|
|
inputFormatters: [
|
|
FilteringTextInputFormatter.digitsOnly,
|
|
LengthLimitingTextInputFormatter(10),
|
|
],
|
|
validator: (value) {
|
|
if (value != null && value.isNotEmpty && value.length < 10) {
|
|
return "Le numéro de mobile doit contenir 10 chiffres";
|
|
}
|
|
return null;
|
|
},
|
|
),
|
|
const SizedBox(height: 16),
|
|
|
|
// Email
|
|
CustomTextField(
|
|
controller: _emailController,
|
|
label: "Email",
|
|
keyboardType: TextInputType.emailAddress,
|
|
readOnly: widget.readOnly,
|
|
validator: (value) {
|
|
if (value == null || value.isEmpty) {
|
|
return "Veuillez entrer l'adresse email";
|
|
}
|
|
if (!value.contains('@') || !value.contains('.')) {
|
|
return "Veuillez entrer une adresse email valide";
|
|
}
|
|
return null;
|
|
},
|
|
),
|
|
const SizedBox(height: 16),
|
|
|
|
// Date de naissance
|
|
CustomTextField(
|
|
controller: _dateNaissanceController,
|
|
label: "Date de naissance",
|
|
readOnly: true,
|
|
onTap: widget.readOnly ? null : () => _selectDate(context, true),
|
|
suffixIcon: Icon(
|
|
Icons.calendar_today,
|
|
color: theme.colorScheme.primary,
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
|
|
// Date d'embauche
|
|
CustomTextField(
|
|
controller: _dateEmbaucheController,
|
|
label: "Date d'embauche",
|
|
readOnly: true,
|
|
onTap: widget.readOnly ? null : () => _selectDate(context, false),
|
|
suffixIcon: Icon(
|
|
Icons.calendar_today,
|
|
color: theme.colorScheme.primary,
|
|
),
|
|
),
|
|
// Espace en bas du formulaire
|
|
const SizedBox(height: 16),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildRadioOption({
|
|
required int value,
|
|
required String label,
|
|
required int groupValue,
|
|
required Function(int?)? onChanged,
|
|
}) {
|
|
final theme = Theme.of(context);
|
|
final isSelected = value == groupValue;
|
|
|
|
return Row(
|
|
children: [
|
|
Radio<int>(
|
|
value: value,
|
|
groupValue: groupValue,
|
|
onChanged: onChanged,
|
|
activeColor: const Color(0xFF20335E),
|
|
),
|
|
Text(
|
|
label,
|
|
style: theme.textTheme.bodyMedium?.copyWith(
|
|
color: theme.colorScheme.onBackground,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|