780 lines
26 KiB
Dart
780 lines
26 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import '../../../../core/widgets/unified_page_layout.dart';
|
|
import '../../../../core/widgets/unified_card.dart';
|
|
import '../../../../core/theme/app_colors.dart';
|
|
import '../../../../core/theme/app_text_styles.dart';
|
|
import '../../domain/entities/notification.dart';
|
|
import '../../domain/entities/preferences_notification.dart';
|
|
import '../bloc/notification_preferences_bloc.dart';
|
|
import '../widgets/preference_section_widget.dart';
|
|
import '../widgets/silent_mode_config_widget.dart';
|
|
|
|
/// Page de configuration des préférences de notifications
|
|
class NotificationPreferencesPage extends StatefulWidget {
|
|
const NotificationPreferencesPage({super.key});
|
|
|
|
@override
|
|
State<NotificationPreferencesPage> createState() => _NotificationPreferencesPageState();
|
|
}
|
|
|
|
class _NotificationPreferencesPageState extends State<NotificationPreferencesPage>
|
|
with TickerProviderStateMixin {
|
|
late TabController _tabController;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_tabController = TabController(length: 3, vsync: this);
|
|
|
|
// Chargement des préférences
|
|
context.read<NotificationPreferencesBloc>().add(
|
|
const LoadPreferencesEvent(),
|
|
);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_tabController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return UnifiedPageLayout(
|
|
title: 'Préférences de notifications',
|
|
showBackButton: true,
|
|
actions: [
|
|
PopupMenuButton<String>(
|
|
icon: const Icon(Icons.more_vert),
|
|
onSelected: (value) {
|
|
switch (value) {
|
|
case 'reset':
|
|
_showResetDialog();
|
|
break;
|
|
case 'test':
|
|
_sendTestNotification();
|
|
break;
|
|
case 'export':
|
|
_exportPreferences();
|
|
break;
|
|
}
|
|
},
|
|
itemBuilder: (context) => [
|
|
const PopupMenuItem(
|
|
value: 'test',
|
|
child: ListTile(
|
|
leading: Icon(Icons.send),
|
|
title: Text('Envoyer un test'),
|
|
contentPadding: EdgeInsets.zero,
|
|
),
|
|
),
|
|
const PopupMenuItem(
|
|
value: 'export',
|
|
child: ListTile(
|
|
leading: Icon(Icons.download),
|
|
title: Text('Exporter'),
|
|
contentPadding: EdgeInsets.zero,
|
|
),
|
|
),
|
|
const PopupMenuDivider(),
|
|
const PopupMenuItem(
|
|
value: 'reset',
|
|
child: ListTile(
|
|
leading: Icon(Icons.restore, color: Colors.red),
|
|
title: Text('Réinitialiser', style: TextStyle(color: Colors.red)),
|
|
contentPadding: EdgeInsets.zero,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
body: BlocBuilder<NotificationPreferencesBloc, NotificationPreferencesState>(
|
|
builder: (context, state) {
|
|
if (state is PreferencesLoading) {
|
|
return const Center(
|
|
child: CircularProgressIndicator(),
|
|
);
|
|
}
|
|
|
|
if (state is PreferencesError) {
|
|
return Center(
|
|
child: UnifiedCard(
|
|
variant: UnifiedCardVariant.outlined,
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(24.0),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(
|
|
Icons.error_outline,
|
|
size: 48,
|
|
color: AppColors.error,
|
|
),
|
|
const SizedBox(height: 16),
|
|
Text(
|
|
'Erreur de chargement',
|
|
style: AppTextStyles.titleMedium,
|
|
),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
state.message,
|
|
style: AppTextStyles.bodyMedium.copyWith(
|
|
color: AppColors.onSurface.withOpacity(0.7),
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
const SizedBox(height: 16),
|
|
ElevatedButton.icon(
|
|
onPressed: () {
|
|
context.read<NotificationPreferencesBloc>().add(
|
|
const LoadPreferencesEvent(),
|
|
);
|
|
},
|
|
icon: const Icon(Icons.refresh),
|
|
label: const Text('Réessayer'),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
if (state is! PreferencesLoaded) {
|
|
return const SizedBox.shrink();
|
|
}
|
|
|
|
return Column(
|
|
children: [
|
|
// Onglets de navigation
|
|
Container(
|
|
margin: const EdgeInsets.all(16.0),
|
|
decoration: BoxDecoration(
|
|
color: AppColors.surface,
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(color: AppColors.outline.withOpacity(0.2)),
|
|
),
|
|
child: TabBar(
|
|
controller: _tabController,
|
|
indicator: BoxDecoration(
|
|
color: AppColors.primary,
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
indicatorSize: TabBarIndicatorSize.tab,
|
|
indicatorPadding: const EdgeInsets.all(4),
|
|
labelColor: AppColors.onPrimary,
|
|
unselectedLabelColor: AppColors.onSurface,
|
|
labelStyle: AppTextStyles.bodyMedium.copyWith(
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
unselectedLabelStyle: AppTextStyles.bodyMedium,
|
|
tabs: const [
|
|
Tab(text: 'Général'),
|
|
Tab(text: 'Types'),
|
|
Tab(text: 'Avancé'),
|
|
],
|
|
),
|
|
),
|
|
|
|
// Contenu des onglets
|
|
Expanded(
|
|
child: TabBarView(
|
|
controller: _tabController,
|
|
children: [
|
|
_buildGeneralTab(state.preferences),
|
|
_buildTypesTab(state.preferences),
|
|
_buildAdvancedTab(state.preferences),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildGeneralTab(PreferencesNotificationEntity preferences) {
|
|
return SingleChildScrollView(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Activation générale
|
|
PreferenceSectionWidget(
|
|
title: 'Notifications',
|
|
subtitle: 'Paramètres généraux des notifications',
|
|
icon: Icons.notifications,
|
|
children: [
|
|
SwitchListTile(
|
|
title: const Text('Activer les notifications'),
|
|
subtitle: const Text('Recevoir toutes les notifications'),
|
|
value: preferences.notificationsActivees,
|
|
onChanged: (value) => _updatePreference(
|
|
preferences.copyWith(notificationsActivees: value),
|
|
),
|
|
),
|
|
|
|
if (preferences.notificationsActivees) ...[
|
|
SwitchListTile(
|
|
title: const Text('Notifications push'),
|
|
subtitle: const Text('Recevoir les notifications sur l\'appareil'),
|
|
value: preferences.pushActivees,
|
|
onChanged: (value) => _updatePreference(
|
|
preferences.copyWith(pushActivees: value),
|
|
),
|
|
),
|
|
|
|
SwitchListTile(
|
|
title: const Text('Notifications par email'),
|
|
subtitle: const Text('Recevoir les notifications par email'),
|
|
value: preferences.emailActivees,
|
|
onChanged: (value) => _updatePreference(
|
|
preferences.copyWith(emailActivees: value),
|
|
),
|
|
),
|
|
|
|
SwitchListTile(
|
|
title: const Text('Notifications SMS'),
|
|
subtitle: const Text('Recevoir les notifications par SMS'),
|
|
value: preferences.smsActivees,
|
|
onChanged: (value) => _updatePreference(
|
|
preferences.copyWith(smsActivees: value),
|
|
),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
|
|
const SizedBox(height: 24),
|
|
|
|
// Mode silencieux
|
|
PreferenceSectionWidget(
|
|
title: 'Mode silencieux',
|
|
subtitle: 'Configurer les périodes de silence',
|
|
icon: Icons.do_not_disturb,
|
|
children: [
|
|
SilentModeConfigWidget(
|
|
preferences: preferences,
|
|
onPreferencesChanged: _updatePreference,
|
|
),
|
|
],
|
|
),
|
|
|
|
const SizedBox(height: 24),
|
|
|
|
// Paramètres visuels et sonores
|
|
PreferenceSectionWidget(
|
|
title: 'Apparence et sons',
|
|
subtitle: 'Personnaliser l\'affichage des notifications',
|
|
icon: Icons.palette,
|
|
children: [
|
|
SwitchListTile(
|
|
title: const Text('Vibration'),
|
|
subtitle: const Text('Faire vibrer l\'appareil'),
|
|
value: preferences.vibrationActivee,
|
|
onChanged: (value) => _updatePreference(
|
|
preferences.copyWith(vibrationActivee: value),
|
|
),
|
|
),
|
|
|
|
SwitchListTile(
|
|
title: const Text('Son'),
|
|
subtitle: const Text('Jouer un son'),
|
|
value: preferences.sonActive,
|
|
onChanged: (value) => _updatePreference(
|
|
preferences.copyWith(sonActive: value),
|
|
),
|
|
),
|
|
|
|
SwitchListTile(
|
|
title: const Text('LED'),
|
|
subtitle: const Text('Allumer la LED de notification'),
|
|
value: preferences.ledActivee,
|
|
onChanged: (value) => _updatePreference(
|
|
preferences.copyWith(ledActivee: value),
|
|
),
|
|
),
|
|
|
|
SwitchListTile(
|
|
title: const Text('Aperçu sur écran verrouillé'),
|
|
subtitle: const Text('Afficher le contenu sur l\'écran verrouillé'),
|
|
value: preferences.apercuEcranVerrouillage,
|
|
onChanged: (value) => _updatePreference(
|
|
preferences.copyWith(apercuEcranVerrouillage: value),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildTypesTab(PreferencesNotificationEntity preferences) {
|
|
return SingleChildScrollView(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'Choisissez les types de notifications que vous souhaitez recevoir',
|
|
style: AppTextStyles.bodyMedium.copyWith(
|
|
color: AppColors.onSurface.withOpacity(0.7),
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 16),
|
|
|
|
// Groupement par catégorie
|
|
..._buildTypesByCategory(preferences),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildAdvancedTab(PreferencesNotificationEntity preferences) {
|
|
return SingleChildScrollView(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Gestion automatique
|
|
PreferenceSectionWidget(
|
|
title: 'Gestion automatique',
|
|
subtitle: 'Paramètres de gestion automatique des notifications',
|
|
icon: Icons.auto_mode,
|
|
children: [
|
|
SwitchListTile(
|
|
title: const Text('Marquage automatique comme lu'),
|
|
subtitle: const Text('Marquer automatiquement les notifications comme lues'),
|
|
value: preferences.marquageLectureAutomatique,
|
|
onChanged: (value) => _updatePreference(
|
|
preferences.copyWith(marquageLectureAutomatique: value),
|
|
),
|
|
),
|
|
|
|
if (preferences.marquageLectureAutomatique)
|
|
ListTile(
|
|
title: const Text('Délai de marquage'),
|
|
subtitle: Text('${preferences.delaiMarquageLectureSecondes ?? 5} secondes'),
|
|
trailing: const Icon(Icons.chevron_right),
|
|
onTap: () => _showDelayPicker(
|
|
'Délai de marquage automatique',
|
|
preferences.delaiMarquageLectureSecondes ?? 5,
|
|
(value) => _updatePreference(
|
|
preferences.copyWith(delaiMarquageLectureSecondes: value),
|
|
),
|
|
),
|
|
),
|
|
|
|
SwitchListTile(
|
|
title: const Text('Archivage automatique'),
|
|
subtitle: const Text('Archiver automatiquement les notifications lues'),
|
|
value: preferences.archivageAutomatique,
|
|
onChanged: (value) => _updatePreference(
|
|
preferences.copyWith(archivageAutomatique: value),
|
|
),
|
|
),
|
|
|
|
if (preferences.archivageAutomatique)
|
|
ListTile(
|
|
title: const Text('Délai d\'archivage'),
|
|
subtitle: Text('${preferences.delaiArchivageHeures} heures'),
|
|
trailing: const Icon(Icons.chevron_right),
|
|
onTap: () => _showDelayPicker(
|
|
'Délai d\'archivage automatique',
|
|
preferences.delaiArchivageHeures,
|
|
(value) => _updatePreference(
|
|
preferences.copyWith(delaiArchivageHeures: value),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
|
|
const SizedBox(height: 24),
|
|
|
|
// Limites et regroupement
|
|
PreferenceSectionWidget(
|
|
title: 'Limites et regroupement',
|
|
subtitle: 'Contrôler le nombre et le regroupement des notifications',
|
|
icon: Icons.group_work,
|
|
children: [
|
|
ListTile(
|
|
title: const Text('Notifications simultanées maximum'),
|
|
subtitle: Text('${preferences.maxNotificationsSimultanees} notifications'),
|
|
trailing: const Icon(Icons.chevron_right),
|
|
onTap: () => _showNumberPicker(
|
|
'Nombre maximum de notifications simultanées',
|
|
preferences.maxNotificationsSimultanees,
|
|
1,
|
|
50,
|
|
(value) => _updatePreference(
|
|
preferences.copyWith(maxNotificationsSimultanees: value),
|
|
),
|
|
),
|
|
),
|
|
|
|
ListTile(
|
|
title: const Text('Fréquence de regroupement'),
|
|
subtitle: Text('${preferences.frequenceRegroupementMinutes} minutes'),
|
|
trailing: const Icon(Icons.chevron_right),
|
|
onTap: () => _showNumberPicker(
|
|
'Fréquence de regroupement des notifications',
|
|
preferences.frequenceRegroupementMinutes,
|
|
1,
|
|
60,
|
|
(value) => _updatePreference(
|
|
preferences.copyWith(frequenceRegroupementMinutes: value),
|
|
),
|
|
),
|
|
),
|
|
|
|
ListTile(
|
|
title: const Text('Durée d\'affichage'),
|
|
subtitle: Text('${preferences.dureeAffichageSecondes} secondes'),
|
|
trailing: const Icon(Icons.chevron_right),
|
|
onTap: () => _showNumberPicker(
|
|
'Durée d\'affichage des notifications',
|
|
preferences.dureeAffichageSecondes,
|
|
3,
|
|
30,
|
|
(value) => _updatePreference(
|
|
preferences.copyWith(dureeAffichageSecondes: value),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
|
|
const SizedBox(height: 24),
|
|
|
|
// Conservation des données
|
|
PreferenceSectionWidget(
|
|
title: 'Conservation des données',
|
|
subtitle: 'Durée de conservation des notifications',
|
|
icon: Icons.storage,
|
|
children: [
|
|
ListTile(
|
|
title: const Text('Durée de conservation'),
|
|
subtitle: Text('${preferences.dureeConservationJours} jours'),
|
|
trailing: const Icon(Icons.chevron_right),
|
|
onTap: () => _showNumberPicker(
|
|
'Durée de conservation des notifications',
|
|
preferences.dureeConservationJours,
|
|
7,
|
|
365,
|
|
(value) => _updatePreference(
|
|
preferences.copyWith(dureeConservationJours: value),
|
|
),
|
|
),
|
|
),
|
|
|
|
SwitchListTile(
|
|
title: const Text('Affichage de l\'historique'),
|
|
subtitle: const Text('Conserver l\'historique des notifications'),
|
|
value: preferences.affichageHistorique,
|
|
onChanged: (value) => _updatePreference(
|
|
preferences.copyWith(affichageHistorique: value),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
List<Widget> _buildTypesByCategory(PreferencesNotificationEntity preferences) {
|
|
final typesByCategory = <String, List<TypeNotification>>{};
|
|
|
|
for (final type in TypeNotification.values) {
|
|
typesByCategory.putIfAbsent(type.categorie, () => []).add(type);
|
|
}
|
|
|
|
return typesByCategory.entries.map((entry) {
|
|
return PreferenceSectionWidget(
|
|
title: _getCategoryTitle(entry.key),
|
|
subtitle: _getCategorySubtitle(entry.key),
|
|
icon: _getCategoryIcon(entry.key),
|
|
children: entry.value.map((type) {
|
|
return SwitchListTile(
|
|
title: Text(type.libelle),
|
|
subtitle: Text(_getTypeDescription(type)),
|
|
value: preferences.isTypeActive(type),
|
|
onChanged: (value) => _toggleNotificationType(type, value),
|
|
secondary: Icon(
|
|
_getTypeIconData(type),
|
|
color: _getTypeColor(type),
|
|
),
|
|
);
|
|
}).toList(),
|
|
);
|
|
}).toList();
|
|
}
|
|
|
|
String _getCategoryTitle(String category) {
|
|
switch (category) {
|
|
case 'evenements':
|
|
return 'Événements';
|
|
case 'cotisations':
|
|
return 'Cotisations';
|
|
case 'solidarite':
|
|
return 'Solidarité';
|
|
case 'membres':
|
|
return 'Membres';
|
|
case 'organisation':
|
|
return 'Organisation';
|
|
case 'messages':
|
|
return 'Messages';
|
|
case 'systeme':
|
|
return 'Système';
|
|
default:
|
|
return category;
|
|
}
|
|
}
|
|
|
|
String _getCategorySubtitle(String category) {
|
|
switch (category) {
|
|
case 'evenements':
|
|
return 'Notifications liées aux événements';
|
|
case 'cotisations':
|
|
return 'Notifications de paiement et cotisations';
|
|
case 'solidarite':
|
|
return 'Demandes d\'aide et solidarité';
|
|
case 'membres':
|
|
return 'Nouveaux membres et anniversaires';
|
|
case 'organisation':
|
|
return 'Annonces et réunions';
|
|
case 'messages':
|
|
return 'Messages privés et mentions';
|
|
case 'systeme':
|
|
return 'Mises à jour et maintenance';
|
|
default:
|
|
return '';
|
|
}
|
|
}
|
|
|
|
IconData _getCategoryIcon(String category) {
|
|
switch (category) {
|
|
case 'evenements':
|
|
return Icons.event;
|
|
case 'cotisations':
|
|
return Icons.payment;
|
|
case 'solidarite':
|
|
return Icons.volunteer_activism;
|
|
case 'membres':
|
|
return Icons.people;
|
|
case 'organisation':
|
|
return Icons.business;
|
|
case 'messages':
|
|
return Icons.message;
|
|
case 'systeme':
|
|
return Icons.settings;
|
|
default:
|
|
return Icons.notifications;
|
|
}
|
|
}
|
|
|
|
String _getTypeDescription(TypeNotification type) {
|
|
// Descriptions courtes pour chaque type
|
|
switch (type) {
|
|
case TypeNotification.nouvelEvenement:
|
|
return 'Nouveaux événements créés';
|
|
case TypeNotification.rappelEvenement:
|
|
return 'Rappels avant les événements';
|
|
case TypeNotification.cotisationDue:
|
|
return 'Échéances de cotisations';
|
|
case TypeNotification.cotisationPayee:
|
|
return 'Confirmations de paiement';
|
|
case TypeNotification.nouvelleDemandeAide:
|
|
return 'Nouvelles demandes d\'aide';
|
|
case TypeNotification.nouveauMembre:
|
|
return 'Nouveaux membres rejoignant';
|
|
case TypeNotification.anniversaireMembre:
|
|
return 'Anniversaires des membres';
|
|
case TypeNotification.annonceGenerale:
|
|
return 'Annonces importantes';
|
|
case TypeNotification.messagePrive:
|
|
return 'Messages privés reçus';
|
|
default:
|
|
return type.libelle;
|
|
}
|
|
}
|
|
|
|
IconData _getTypeIconData(TypeNotification type) {
|
|
switch (type.icone) {
|
|
case 'event':
|
|
return Icons.event;
|
|
case 'payment':
|
|
return Icons.payment;
|
|
case 'help':
|
|
return Icons.help;
|
|
case 'person_add':
|
|
return Icons.person_add;
|
|
case 'cake':
|
|
return Icons.cake;
|
|
case 'campaign':
|
|
return Icons.campaign;
|
|
case 'mail':
|
|
return Icons.mail;
|
|
default:
|
|
return Icons.notifications;
|
|
}
|
|
}
|
|
|
|
Color _getTypeColor(TypeNotification type) {
|
|
try {
|
|
return Color(int.parse(type.couleur.replaceFirst('#', '0xFF')));
|
|
} catch (e) {
|
|
return AppColors.primary;
|
|
}
|
|
}
|
|
|
|
void _updatePreference(PreferencesNotificationEntity preferences) {
|
|
context.read<NotificationPreferencesBloc>().add(
|
|
UpdatePreferencesEvent(preferences: preferences),
|
|
);
|
|
}
|
|
|
|
void _toggleNotificationType(TypeNotification type, bool active) {
|
|
context.read<NotificationPreferencesBloc>().add(
|
|
ToggleNotificationTypeEvent(type: type, active: active),
|
|
);
|
|
}
|
|
|
|
void _showResetDialog() {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: const Text('Réinitialiser les préférences'),
|
|
content: const Text(
|
|
'Êtes-vous sûr de vouloir réinitialiser toutes vos préférences '
|
|
'de notifications aux valeurs par défaut ?',
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(context),
|
|
child: const Text('Annuler'),
|
|
),
|
|
TextButton(
|
|
onPressed: () {
|
|
Navigator.pop(context);
|
|
context.read<NotificationPreferencesBloc>().add(
|
|
const ResetPreferencesEvent(),
|
|
);
|
|
},
|
|
style: TextButton.styleFrom(
|
|
foregroundColor: AppColors.error,
|
|
),
|
|
child: const Text('Réinitialiser'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
void _sendTestNotification() {
|
|
context.read<NotificationPreferencesBloc>().add(
|
|
const SendTestNotificationEvent(type: TypeNotification.annonceGenerale),
|
|
);
|
|
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text('Notification de test envoyée'),
|
|
duration: Duration(seconds: 2),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _exportPreferences() {
|
|
context.read<NotificationPreferencesBloc>().add(
|
|
const ExportPreferencesEvent(),
|
|
);
|
|
}
|
|
|
|
void _showDelayPicker(String title, int currentValue, Function(int) onChanged) {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: Text(title),
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Text('Valeur actuelle: $currentValue secondes'),
|
|
const SizedBox(height: 16),
|
|
// Ici vous pourriez ajouter un slider ou un picker
|
|
// Pour simplifier, on utilise des boutons prédéfinis
|
|
Wrap(
|
|
spacing: 8,
|
|
children: [5, 10, 15, 30, 60].map((value) {
|
|
return ChoiceChip(
|
|
label: Text('${value}s'),
|
|
selected: currentValue == value,
|
|
onSelected: (selected) {
|
|
if (selected) {
|
|
onChanged(value);
|
|
Navigator.pop(context);
|
|
}
|
|
},
|
|
);
|
|
}).toList(),
|
|
),
|
|
],
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(context),
|
|
child: const Text('Annuler'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
void _showNumberPicker(
|
|
String title,
|
|
int currentValue,
|
|
int min,
|
|
int max,
|
|
Function(int) onChanged,
|
|
) {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: Text(title),
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Text('Valeur actuelle: $currentValue'),
|
|
const SizedBox(height: 16),
|
|
// Slider pour choisir la valeur
|
|
Slider(
|
|
value: currentValue.toDouble(),
|
|
min: min.toDouble(),
|
|
max: max.toDouble(),
|
|
divisions: max - min,
|
|
label: currentValue.toString(),
|
|
onChanged: (value) {
|
|
// Mise à jour en temps réel
|
|
},
|
|
onChangeEnd: (value) {
|
|
onChanged(value.round());
|
|
Navigator.pop(context);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(context),
|
|
child: const Text('Annuler'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|