您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

196 行
6.1KB

  1. import 'package:flutter/material.dart';
  2. import '../../../data/models/user_profile.dart';
  3. // L'import des routes n'est plus nécessaire ici pour la navigation, mais on le garde pour la propreté.
  4. final class ProfileSetupScreen extends StatefulWidget {
  5. const ProfileSetupScreen({super.key});
  6. @override
  7. State<ProfileSetupScreen> createState() => _ProfileSetupScreenState();
  8. }
  9. class _ProfileSetupScreenState extends State<ProfileSetupScreen> {
  10. final List<UserProfile> _profiles = [];
  11. @override
  12. void initState() {
  13. super.initState();
  14. _addProfile();
  15. }
  16. void _addProfile() {
  17. setState(() {
  18. _profiles.add(
  19. const UserProfile(
  20. profession: '',
  21. tone: MessageTone.normal,
  22. textStyle: TextStyleEnum.classic,
  23. ),
  24. );
  25. });
  26. }
  27. void _updateProfile(int index, UserProfile profile) {
  28. setState(() => _profiles[index] = profile);
  29. }
  30. void _removeProfile(int index) {
  31. if (_profiles.length > 1) {
  32. setState(() => _profiles.removeAt(index));
  33. }
  34. }
  35. @override
  36. Widget build(BuildContext context) => Scaffold(
  37. appBar: AppBar(title: const Text('Créer votre profil')),
  38. body: SafeArea(
  39. child: Column(
  40. children: [
  41. Expanded(
  42. child: SingleChildScrollView(
  43. padding: const EdgeInsets.all(20),
  44. child: Column(
  45. crossAxisAlignment: CrossAxisAlignment.start,
  46. children: [
  47. Text(
  48. 'Configurez vos profils',
  49. style: Theme.of(context).textTheme.headlineSmall,
  50. ),
  51. const SizedBox(height: 24),
  52. ..._profiles.asMap().entries.map((e) {
  53. final (index, profile) = (e.key, e.value);
  54. return _ProfileCard(
  55. profile: profile,
  56. onUpdate: (p) => _updateProfile(index, p),
  57. onRemove: _profiles.length > 1
  58. ? () => _removeProfile(index)
  59. : null,
  60. index: index,
  61. );
  62. }),
  63. if (_profiles.length < 5) ...[
  64. const SizedBox(height: 16),
  65. OutlinedButton.icon(
  66. onPressed: _addProfile,
  67. icon: const Icon(Icons.add),
  68. label: const Text('Ajouter un profil'),
  69. ),
  70. ],
  71. ],
  72. ),
  73. ),
  74. ),
  75. Container(
  76. padding: const EdgeInsets.all(20),
  77. child: SizedBox(
  78. width: double.infinity,
  79. child: FilledButton(
  80. onPressed: _profiles.any((p) => p.profession.isNotEmpty)
  81. ? () {
  82. // --- CORRECTION ---
  83. // 1. Logique pour sauvegarder les profils (à ajouter si nécessaire)
  84. //
  85. // 2. On ferme simplement l'écran de configuration pour revenir
  86. // à l'écran qui l'a appelé (HomeScreen).
  87. Navigator.pop(context);
  88. }
  89. : null,
  90. child: const Text('Enregistrer et Terminer'),
  91. ),
  92. ),
  93. ),
  94. ],
  95. ),
  96. ),
  97. );
  98. }
  99. // ... Le widget _ProfileCard reste inchangé ...
  100. class _ProfileCard extends StatefulWidget {
  101. const _ProfileCard({
  102. required this.profile,
  103. required this.onUpdate,
  104. required this.index, this.onRemove,
  105. });
  106. final UserProfile profile;
  107. final Function(UserProfile) onUpdate;
  108. final VoidCallback? onRemove;
  109. final int index;
  110. @override
  111. State<_ProfileCard> createState() => _ProfileCardState();
  112. }
  113. class _ProfileCardState extends State<_ProfileCard> {
  114. late final TextEditingController _controller;
  115. @override
  116. void initState() {
  117. super.initState();
  118. _controller = TextEditingController(text: widget.profile.profession);
  119. }
  120. @override
  121. void didUpdateWidget(_ProfileCard oldWidget) {
  122. super.didUpdateWidget(oldWidget);
  123. if (widget.profile.profession != _controller.text) {
  124. _controller.text = widget.profile.profession;
  125. }
  126. }
  127. @override
  128. void dispose() {
  129. _controller.dispose();
  130. super.dispose();
  131. }
  132. @override
  133. Widget build(BuildContext context) => Card(
  134. margin: const EdgeInsets.only(bottom: 16),
  135. child: Padding(
  136. padding: const EdgeInsets.all(16),
  137. child: Column(
  138. crossAxisAlignment: CrossAxisAlignment.start,
  139. children: [
  140. Row(
  141. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  142. children: [
  143. Text('Profil ${widget.index + 1}'),
  144. if (widget.onRemove != null)
  145. IconButton(icon: const Icon(Icons.close), onPressed: widget.onRemove),
  146. ],
  147. ),
  148. const SizedBox(height: 16),
  149. TextField(
  150. controller: _controller,
  151. decoration: const InputDecoration(labelText: 'Métier'),
  152. onChanged: (v) => widget.onUpdate(widget.profile.copyWith(profession: v)),
  153. ),
  154. const SizedBox(height: 16),
  155. Text('Ton:', style: Theme.of(context).textTheme.bodySmall),
  156. Wrap(
  157. spacing: 8,
  158. children: MessageTone.values.map((t) => FilterChip(
  159. label: Text(t.displayName),
  160. selected: widget.profile.tone == t,
  161. onSelected: (_) => widget.onUpdate(widget.profile.copyWith(tone: t)),
  162. )).toList(),
  163. ),
  164. const SizedBox(height: 16),
  165. Text('Style:', style: Theme.of(context).textTheme.bodySmall),
  166. Wrap(
  167. spacing: 8,
  168. children: TextStyleEnum.values.map((s) => FilterChip(
  169. label: Text(s.displayName),
  170. selected: widget.profile.textStyle == s,
  171. onSelected: (_) => widget.onUpdate(widget.profile.copyWith(textStyle: s)),
  172. )).toList(),
  173. ),
  174. ],
  175. ),
  176. ),
  177. );
  178. }