Julien Martin b8faf3b4df Ajoute l'espace parent : PIN, grille de règles, historique et annulation.
Phase 2 du MVP Flutter : vérification PIN locale, application des règles par famille, suivi des mouvements et correction avec plancher à 0.

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

96 lines
3.3 KiB
Dart

import 'package:flutter/material.dart';
import '../../../data/database/app_database.dart';
class RulesGrid extends StatelessWidget {
const RulesGrid({
super.key,
required this.rules,
required this.isApplying,
required this.onRuleTap,
});
final List<Regle> rules;
final bool isApplying;
final void Function(int ruleId) onRuleTap;
@override
Widget build(BuildContext context) {
final groups = <String, List<Regle>>{};
for (final rule in rules) {
groups.putIfAbsent(rule.famille, () => []).add(rule);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: groups.entries.map((entry) {
return Padding(
padding: const EdgeInsets.only(bottom: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
entry.key,
style: Theme.of(context).textTheme.titleSmall?.copyWith(
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
Wrap(
spacing: 8,
runSpacing: 8,
children: entry.value.map((rule) {
final positive = rule.points >= 0;
return Material(
color: positive
? Colors.green.shade50
: Colors.red.shade50,
borderRadius: BorderRadius.circular(12),
child: InkWell(
onTap: isApplying ? null : () => onRuleTap(rule.id),
borderRadius: BorderRadius.circular(12),
child: Container(
width: 160,
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: positive
? Colors.green.shade200
: Colors.red.shade200,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${rule.icone} ${rule.libelle}',
style: const TextStyle(fontSize: 13),
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 4),
Text(
'${rule.points > 0 ? '+' : ''}${rule.points}',
style: TextStyle(
fontWeight: FontWeight.bold,
color: positive
? Colors.green.shade800
: Colors.red.shade800,
),
),
],
),
),
),
);
}).toList(),
),
],
),
);
}).toList(),
);
}
}