Julien Martin aac3a729a2 Initialise l'app Flutter mobile : BDD Drift, onboarding sans compte et tableau de bord.
Phase 1 du MVP : schéma SQLite porté depuis le prototype web, seed des règles/récompenses, flux d'onboarding en 4 étapes et écran d'accueil minimal.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-12 12:12:01 +02:00

118 lines
3.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../data/seed/default_rewards.dart';
import '../../../data/seed/default_rules.dart';
import '../onboarding_state.dart';
import '../widgets/onboarding_scaffold.dart';
class RulesStep extends ConsumerWidget {
const RulesStep({
super.key,
required this.step,
required this.isSaving,
required this.onBack,
required this.onFinish,
});
final int step;
final bool isSaving;
final VoidCallback onBack;
final VoidCallback onFinish;
@override
Widget build(BuildContext context, WidgetRef ref) {
final draft = ref.watch(onboardingDraftProvider);
final notifier = ref.read(onboardingDraftProvider.notifier);
return OnboardingScaffold(
step: step,
title: 'Règles par défaut',
subtitle: 'Pack « Maison & école » prêt à l\'emploi',
child: Card(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SwitchListTile(
contentPadding: EdgeInsets.zero,
title: const Text('Importer le pack par défaut'),
subtitle: Text(
'${defaultRules.length} règles et '
'${defaultRewards.length} récompenses',
),
value: draft.importDefaultRules,
onChanged: isSaving ? null : notifier.setImportDefaultRules,
),
const Divider(),
Expanded(
child: draft.importDefaultRules
? ListView(
children: [
Text(
'Familles de règles incluses :',
style: Theme.of(context).textTheme.titleSmall,
),
const SizedBox(height: 8),
..._ruleFamilies.map(
(f) => Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Text('$f'),
),
),
const SizedBox(height: 16),
Text(
'Vous pourrez modifier les règles plus tard '
'depuis l\'espace parent (Premium pour '
'l\'édition complète).',
style: Theme.of(context).textTheme.bodySmall
?.copyWith(color: Colors.grey.shade600),
),
],
)
: Center(
child: Text(
'Vous partirez sans règles ni récompenses. '
'Vous pourrez les ajouter manuellement plus tard.',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyMedium,
),
),
),
],
),
),
),
bottom: Row(
children: [
TextButton(
onPressed: isSaving ? null : onBack,
child: const Text('Retour'),
),
const Spacer(),
FilledButton(
onPressed: isSaving ? null : onFinish,
child: isSaving
? const SizedBox(
width: 22,
height: 22,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Text('C\'est parti !'),
),
],
),
);
}
}
const _ruleFamilies = [
RuleFamilies.maison,
RuleFamilies.routine,
RuleFamilies.fratrie,
RuleFamilies.respect,
RuleFamilies.ecrans,
RuleFamilies.bonus,
];