Feat: Bouton de clôture de session (80/20) sur l'accueil et reset de l'espacement

This commit is contained in:
qguillaume
2026-05-26 14:59:25 +02:00
parent fbd631c8e4
commit 0af6a0d8e2
3 changed files with 196 additions and 168 deletions

View File

@@ -496,13 +496,13 @@ class AnalysisProvider extends ChangeNotifier {
/// Adjust target position /// Adjust target position
void adjustTargetPosition( void adjustTargetPosition(
double centerX, double centerX,
double centerY, double centerY,
double innerRadius, double innerRadius,
double radius, { double radius, {
int? ringCount, int? ringCount,
List<double>? ringRadii, List<double>? ringRadii,
}) { }) {
_targetCenterX = centerX; _targetCenterX = centerX;
_targetCenterY = centerY; _targetCenterY = centerY;
_targetInnerRadius = innerRadius; _targetInnerRadius = innerRadius;
@@ -510,9 +510,9 @@ class AnalysisProvider extends ChangeNotifier {
if (ringCount != null) { if (ringCount != null) {
_ringCount = ringCount; _ringCount = ringCount;
} }
if (ringRadii != null) {
_ringRadii = ringRadii; // CORRECTION : On accepte désormais la valeur null pour pouvoir réinitialiser l'espacement !
} _ringRadii = ringRadii;
// Recalculate all shot scores based on new target position // Recalculate all shot scores based on new target position
_shots = _shots.map((shot) { _shots = _shots.map((shot) {

View File

@@ -51,14 +51,14 @@ class TargetCalibrationState extends State<TargetCalibration> {
late int _ringCount; late int _ringCount;
late List<double> _ringRadii; late List<double> _ringRadii;
// CORRECTION : Variable dédiée pour piloter la jauge orange sans conflit
late double _currentEspacementRatio;
bool _isDraggingCenter = false; bool _isDraggingCenter = false;
bool _isDraggingRadius = false; bool _isDraggingRadius = false;
bool _isDraggingInnerRadius = false; bool _isDraggingInnerRadius = false;
// Contrôle de l'affichage du scroll d'espacement (désactivé par défaut)
bool _showEspacement = false; bool _showEspacement = false;
// Variable temporaire pour stocker la valeur du rayon au début du pincement tactile
double _baseRadiusBeforeScale = 1.0; double _baseRadiusBeforeScale = 1.0;
@override @override
@@ -69,6 +69,9 @@ class TargetCalibrationState extends State<TargetCalibration> {
_radius = widget.initialRadius; _radius = widget.initialRadius;
_innerRadius = widget.initialInnerRadius; _innerRadius = widget.initialInnerRadius;
_ringCount = widget.initialRingCount; _ringCount = widget.initialRingCount;
// Initialisation du ratio par défaut
_currentEspacementRatio = (_radius > 0) ? (_innerRadius / _radius).clamp(0.01, 0.9) : 0.1;
_initRingRadii(); _initRingRadii();
} }
@@ -77,11 +80,9 @@ class TargetCalibrationState extends State<TargetCalibration> {
widget.initialRingRadii!.length == _ringCount) { widget.initialRingRadii!.length == _ringCount) {
_ringRadii = List.from(widget.initialRingRadii!); _ringRadii = List.from(widget.initialRingRadii!);
} else { } else {
// Initialize with default proportional radii interpolated between inner and outer
_ringRadii = List.generate(_ringCount, (i) { _ringRadii = List.generate(_ringCount, (i) {
if (_ringCount <= 1) return 1.0; if (_ringCount <= 1) return 1.0;
final ratio = _innerRadius / _radius; return _currentEspacementRatio + (1.0 - _currentEspacementRatio) * i / (_ringCount - 1);
return ratio + (1.0 - ratio) * i / (_ringCount - 1);
}); });
} }
} }
@@ -91,12 +92,10 @@ class TargetCalibrationState extends State<TargetCalibration> {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
bool shouldReinit = false; bool shouldReinit = false;
if (widget.initialCenterX != oldWidget.initialCenterX && if (widget.initialCenterX != oldWidget.initialCenterX && !_isDraggingCenter) {
!_isDraggingCenter) {
_centerX = widget.initialCenterX; _centerX = widget.initialCenterX;
} }
if (widget.initialCenterY != oldWidget.initialCenterY && if (widget.initialCenterY != oldWidget.initialCenterY && !_isDraggingCenter) {
!_isDraggingCenter) {
_centerY = widget.initialCenterY; _centerY = widget.initialCenterY;
} }
if (widget.initialRingCount != oldWidget.initialRingCount) { if (widget.initialRingCount != oldWidget.initialRingCount) {
@@ -107,12 +106,12 @@ class TargetCalibrationState extends State<TargetCalibration> {
_radius = widget.initialRadius; _radius = widget.initialRadius;
shouldReinit = true; shouldReinit = true;
} }
if (widget.initialInnerRadius != oldWidget.initialInnerRadius && if (widget.initialInnerRadius != oldWidget.initialInnerRadius && !_isDraggingInnerRadius) {
!_isDraggingInnerRadius) {
_innerRadius = widget.initialInnerRadius; _innerRadius = widget.initialInnerRadius;
_currentEspacementRatio = (_radius > 0) ? (_innerRadius / _radius).clamp(0.01, 0.9) : 0.1;
shouldReinit = true; shouldReinit = true;
} }
if (widget.initialRingRadii != oldWidget.initialRingRadii) { if (widget.initialRingRadii != oldWidget.initialRingRadii && widget.initialRingRadii != null) {
shouldReinit = true; shouldReinit = true;
} }
@@ -129,7 +128,6 @@ class TargetCalibrationState extends State<TargetCalibration> {
return Stack( return Stack(
children: [ children: [
// Utilisation d'un Gesture Detector basé sur le Scale pour synchroniser à 1 ou 2 doigts
GestureDetector( GestureDetector(
onScaleStart: (details) { onScaleStart: (details) {
_baseRadiusBeforeScale = _radius; _baseRadiusBeforeScale = _radius;
@@ -162,7 +160,6 @@ class TargetCalibrationState extends State<TargetCalibration> {
), ),
), ),
// Panneau de configuration des Sliders en haut
Positioned( Positioned(
top: 10, top: 10,
left: 40, left: 40,
@@ -170,7 +167,6 @@ class TargetCalibrationState extends State<TargetCalibration> {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
// Ligne d'activation pour afficher ou masquer l'espacement
Container( Container(
margin: const EdgeInsets.only(bottom: 8), margin: const EdgeInsets.only(bottom: 8),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 2), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 2),
@@ -201,7 +197,6 @@ class TargetCalibrationState extends State<TargetCalibration> {
), ),
), ),
// Slider pour la taille (toujours visible)
Container( Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -221,6 +216,7 @@ class TargetCalibrationState extends State<TargetCalibration> {
onChanged: (value) { onChanged: (value) {
setState(() { setState(() {
_radius = value; _radius = value;
_innerRadius = _radius * _currentEspacementRatio;
_initRingRadii(forceRecalculate: true); _initRingRadii(forceRecalculate: true);
}); });
_notifyChange(); _notifyChange();
@@ -232,11 +228,10 @@ class TargetCalibrationState extends State<TargetCalibration> {
), ),
), ),
// Affichage conditionnel du slider d'espacement orange
if (_showEspacement) ...[ if (_showEspacement) ...[
const SizedBox(height: 8), const SizedBox(height: 8),
Container( Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), padding: const EdgeInsets.fromLTRB(16, 4, 4, 4),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.black54, color: Colors.black54,
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
@@ -246,21 +241,51 @@ class TargetCalibrationState extends State<TargetCalibration> {
const Text('Espacement ', style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold)), const Text('Espacement ', style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold)),
const Icon(Icons.compress, color: Colors.white, size: 16), const Icon(Icons.compress, color: Colors.white, size: 16),
Expanded( Expanded(
child: Slider( child: Row(
value: (_innerRadius / _radius).clamp(0.01, 0.9), children: [
min: 0.01, Expanded(
max: 0.9, child: Slider(
activeColor: Colors.orange, value: _currentEspacementRatio,
onChanged: (value) { min: 0.01,
setState(() { max: 0.9,
_innerRadius = _radius * value; activeColor: Colors.orange,
_initRingRadii(forceRecalculate: true); onChanged: (value) {
}); setState(() {
_notifyChange(); _currentEspacementRatio = value;
}, _innerRadius = _radius * _currentEspacementRatio;
_initRingRadii(forceRecalculate: true);
});
_notifyChange();
},
),
),
const Icon(Icons.expand, color: Colors.white, size: 16),
],
), ),
), ),
const Icon(Icons.expand, color: Colors.white, size: 16), // CORRECTION DU BOUTON RESET : Force visuellement le ratio par défaut
// CORRECTION RADICALE : On force le ratio à 0.1 (10% standard) en dur
IconButton(
icon: const Icon(Icons.refresh, color: Colors.white70, size: 20),
onPressed: () {
setState(() {
// 1. On force la jauge orange à se remettre pile à 10% (la valeur d'usine)
_currentEspacementRatio = 0.1;
// 2. On réaligne l'innerRadius sur la taille actuelle
_innerRadius = _radius * _currentEspacementRatio;
// 3. On force la reconstruction des cercles parfaits
_initRingRadii(forceRecalculate: true);
});
// 4. On balance tout ça au provider pour qu'il s'aligne
_notifyChange();
},
tooltip: 'Réinitialiser l\'espacement',
constraints: const BoxConstraints(),
padding: const EdgeInsets.symmetric(horizontal: 8),
),
], ],
), ),
), ),
@@ -268,7 +293,6 @@ class TargetCalibrationState extends State<TargetCalibration> {
], ],
), ),
), ),
], ],
); );
}, },
@@ -286,28 +310,16 @@ class TargetCalibrationState extends State<TargetCalibration> {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
_buildDirectionButton( _buildDirectionButton(Icons.keyboard_arrow_up, () => _moveCenterByPixels(0, -1, size)),
Icons.keyboard_arrow_up,
() => _moveCenterByPixels(0, -1, size),
),
Row( Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
_buildDirectionButton( _buildDirectionButton(Icons.keyboard_arrow_left, () => _moveCenterByPixels(-1, 0, size)),
Icons.keyboard_arrow_left,
() => _moveCenterByPixels(-1, 0, size),
),
const SizedBox(width: 40), const SizedBox(width: 40),
_buildDirectionButton( _buildDirectionButton(Icons.keyboard_arrow_right, () => _moveCenterByPixels(1, 0, size)),
Icons.keyboard_arrow_right,
() => _moveCenterByPixels(1, 0, size),
),
], ],
), ),
_buildDirectionButton( _buildDirectionButton(Icons.keyboard_arrow_down, () => _moveCenterByPixels(0, 1, size)),
Icons.keyboard_arrow_down,
() => _moveCenterByPixels(0, 1, size),
),
], ],
), ),
); );
@@ -315,10 +327,7 @@ class TargetCalibrationState extends State<TargetCalibration> {
Widget _buildDirectionButton(IconData icon, VoidCallback onPressed) { Widget _buildDirectionButton(IconData icon, VoidCallback onPressed) {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(color: Colors.black87, borderRadius: BorderRadius.circular(8)),
color: Colors.black87,
borderRadius: BorderRadius.circular(8),
),
margin: const EdgeInsets.all(2), margin: const EdgeInsets.all(2),
child: IconButton( child: IconButton(
icon: Icon(icon, color: Colors.white, size: 28), icon: Icon(icon, color: Colors.white, size: 28),
@@ -348,22 +357,19 @@ class TargetCalibrationState extends State<TargetCalibration> {
_notifyChange(); _notifyChange();
} }
// Traitement intelligent des gestes tactiles
void _onScaleUpdate(ScaleUpdateDetails details, Size size) { void _onScaleUpdate(ScaleUpdateDetails details, Size size) {
setState(() { setState(() {
if (details.pointerCount == 2) { if (details.pointerCount == 2) {
// GESTE À DEUX DOIGTS : On calcule le zoom en respectant le range strict (0.3 à 1.2)
_radius = (_baseRadiusBeforeScale * details.scale).clamp(0.5, 1.1); _radius = (_baseRadiusBeforeScale * details.scale).clamp(0.5, 1.1);
_innerRadius = _radius * _currentEspacementRatio;
_initRingRadii(forceRecalculate: true); _initRingRadii(forceRecalculate: true);
} else if (_isDraggingCenter) { } else if (_isDraggingCenter) {
// GESTE À UN SEUL DOIGT : Déplacement fluide du centre de la cible
final deltaX = details.focalPointDelta.dx / size.width; final deltaX = details.focalPointDelta.dx / size.width;
final deltaY = details.focalPointDelta.dy / size.height; final deltaY = details.focalPointDelta.dy / size.height;
_centerX = _centerX + deltaX; _centerX = _centerX + deltaX;
_centerY = _centerY + deltaY; _centerY = _centerY + deltaY;
} }
}); });
_notifyChange(); _notifyChange();
} }
@@ -420,31 +426,16 @@ class _CalibrationPainter extends CustomPainter {
} }
if (isDraggingCenter) { if (isDraggingCenter) {
final crosshairLinePaint = Paint() final crosshairLinePaint = Paint()..color = Colors.red.withValues(alpha: 0.5)..strokeWidth = 1;
..color = Colors.red.withValues(alpha: 0.5) canvas.drawLine(Offset(0, centerPx.dy), Offset(size.width, centerPx.dy), crosshairLinePaint);
..strokeWidth = 1; canvas.drawLine(Offset(centerPx.dx, 0), Offset(centerPx.dx, size.height), crosshairLinePaint);
canvas.drawLine(
Offset(0, centerPx.dy),
Offset(size.width, centerPx.dy),
crosshairLinePaint,
);
canvas.drawLine(
Offset(centerPx.dx, 0),
Offset(centerPx.dx, size.height),
crosshairLinePaint,
);
} }
_drawCenterHandle(canvas, centerPx); _drawCenterHandle(canvas, centerPx);
_drawInstructions(canvas, size); _drawInstructions(canvas, size);
} }
void _drawConcentricZones( void _drawConcentricZones(Canvas canvas, Size size, Offset center, double baseRadius) {
Canvas canvas,
Size size,
Offset center,
double baseRadius,
) {
List<Color> zoneColors = []; List<Color> zoneColors = [];
for (int i = 0; i < ringCount; i++) { for (int i = 0; i < ringCount; i++) {
final ratio = i / ringCount; final ratio = i / ringCount;
@@ -468,9 +459,7 @@ class _CalibrationPainter extends CustomPainter {
..color = Colors.red.withValues(alpha: 0.8); ..color = Colors.red.withValues(alpha: 0.8);
for (int i = ringCount - 1; i >= 0; i--) { for (int i = ringCount - 1; i >= 0; i--) {
final ringRadius = ringRadii.length > i final ringRadius = ringRadii.length > i ? ringRadii[i] : (i + 1) / ringCount;
? ringRadii[i]
: (i + 1) / ringCount;
final zoneRadius = baseRadius * ringRadius; final zoneRadius = baseRadius * ringRadius;
zonePaint.color = zoneColors[i]; zonePaint.color = zoneColors[i];
@@ -481,12 +470,8 @@ class _CalibrationPainter extends CustomPainter {
final textPainter = TextPainter(textDirection: TextDirection.ltr); final textPainter = TextPainter(textDirection: TextDirection.ltr);
for (int i = 0; i < ringCount; i++) { for (int i = 0; i < ringCount; i++) {
final ringRadius = ringRadii.length > i final ringRadius = ringRadii.length > i ? ringRadii[i] : (i + 1) / ringCount;
? ringRadii[i] final prevRingRadius = i > 0 ? (ringRadii.length > i - 1 ? ringRadii[i - 1] : i / ringCount) : 0.0;
: (i + 1) / ringCount;
final prevRingRadius = i > 0
? (ringRadii.length > i - 1 ? ringRadii[i - 1] : i / ringCount)
: 0.0;
final zoneRadius = baseRadius * (ringRadius + prevRingRadius) / 2; final zoneRadius = baseRadius * (ringRadius + prevRingRadius) / 2;
final score = 10 - i; final score = 10 - i;
@@ -506,53 +491,28 @@ class _CalibrationPainter extends CustomPainter {
final labelY = center.dy - textPainter.height / 2; final labelY = center.dy - textPainter.height / 2;
if (labelY >= 0 && labelY <= size.height) { if (labelY >= 0 && labelY <= size.height) {
textPainter.paint( textPainter.paint(canvas, Offset(labelX - textPainter.width / 2, labelY));
canvas,
Offset(labelX - textPainter.width / 2, labelY),
);
} }
} }
} }
void _drawSilhouetteZones( void _drawSilhouetteZones(Canvas canvas, Size size, Offset center, double radius) {
Canvas canvas, final paint = Paint()..style = PaintingStyle.stroke..strokeWidth = 2;
Size size,
Offset center,
double radius,
) {
final paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 2;
final silhouetteWidth = radius * 0.8; final silhouetteWidth = radius * 0.8;
final silhouetteHeight = radius * 2; final silhouetteHeight = radius * 2;
paint.color = Colors.green.withValues(alpha: 0.5); paint.color = Colors.green.withValues(alpha: 0.5);
canvas.drawRect( canvas.drawRect(Rect.fromCenter(center: center, width: silhouetteWidth, height: silhouetteHeight), paint);
Rect.fromCenter(
center: center,
width: silhouetteWidth,
height: silhouetteHeight,
),
paint,
);
} }
void _drawCenterHandle(Canvas canvas, Offset center) { void _drawCenterHandle(Canvas canvas, Offset center) {
final outerPaint = Paint() final outerPaint = Paint()..color = isDraggingCenter ? Colors.redAccent : Colors.red..style = PaintingStyle.stroke..strokeWidth = 3;
..color = isDraggingCenter ? Colors.redAccent : Colors.red
..style = PaintingStyle.stroke
..strokeWidth = 3;
canvas.drawCircle(center, 15, outerPaint); canvas.drawCircle(center, 15, outerPaint);
final innerPaint = Paint() final innerPaint = Paint()..color = isDraggingCenter ? Colors.redAccent : Colors.red..style = PaintingStyle.fill;
..color = isDraggingCenter ? Colors.redAccent : Colors.red
..style = PaintingStyle.fill;
canvas.drawCircle(center, 5, innerPaint); canvas.drawCircle(center, 5, innerPaint);
final crossPaint = Paint() final crossPaint = Paint()..color = isDraggingCenter ? Colors.redAccent : Colors.red..strokeWidth = 2;
..color = isDraggingCenter ? Colors.redAccent : Colors.red
..strokeWidth = 2;
canvas.drawLine(Offset(center.dx - 20, center.dy), Offset(center.dx - 8, center.dy), crossPaint); canvas.drawLine(Offset(center.dx - 20, center.dy), Offset(center.dx - 8, center.dy), crossPaint);
canvas.drawLine(Offset(center.dx + 8, center.dy), Offset(center.dx + 20, center.dy), crossPaint); canvas.drawLine(Offset(center.dx + 8, center.dy), Offset(center.dx + 20, center.dy), crossPaint);
canvas.drawLine(Offset(center.dx, center.dy - 20), Offset(center.dx, center.dy - 8), crossPaint); canvas.drawLine(Offset(center.dx, center.dy - 20), Offset(center.dx, center.dy - 8), crossPaint);
@@ -561,23 +521,12 @@ class _CalibrationPainter extends CustomPainter {
void _drawInstructions(Canvas canvas, Size size) { void _drawInstructions(Canvas canvas, Size size) {
const instruction = 'Deplacez le centre ou ajustez le rayon'; const instruction = 'Deplacez le centre ou ajustez le rayon';
final textPainter = TextPainter( final textPainter = TextPainter(
text: TextSpan( text: TextSpan(text: instruction, style: TextStyle(color: Colors.white.withValues(alpha: 0.9), fontSize: 12, backgroundColor: Colors.black54)),
text: instruction,
style: TextStyle(
color: Colors.white.withValues(alpha: 0.9),
fontSize: 12,
backgroundColor: Colors.black54,
),
),
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
); );
textPainter.layout(); textPainter.layout();
textPainter.paint( textPainter.paint(canvas, Offset((size.width - textPainter.width) / 2, size.height - 30));
canvas,
Offset((size.width - textPainter.width) / 2, size.height - 30),
);
} }
@override @override

View File

@@ -125,21 +125,100 @@ class _HomeScreenState extends State<HomeScreen> {
final sessionProvider = context.watch<SessionProvider>(); final sessionProvider = context.watch<SessionProvider>();
final isSessionActive = sessionProvider.isSessionActive; final isSessionActive = sessionProvider.isSessionActive;
return ElevatedButton.icon( // Si aucune session n'est active, on affiche juste le bouton de départ habituel
onPressed: () => _navigateToSessionSetup(context), if (!isSessionActive) {
style: ElevatedButton.styleFrom( return ElevatedButton.icon(
backgroundColor: isSessionActive ? AppTheme.secondaryColor : AppTheme.primaryColor, onPressed: () => _navigateToSessionSetup(context),
foregroundColor: Colors.white, style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 20), backgroundColor: AppTheme.primaryColor,
shape: RoundedRectangleBorder( foregroundColor: Colors.white,
borderRadius: BorderRadius.circular(AppConstants.borderRadius), padding: const EdgeInsets.symmetric(vertical: 20),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppConstants.borderRadius),
),
), ),
), icon: const Icon(Icons.add_circle_outline, size: 28),
icon: Icon(isSessionActive ? Icons.play_circle_outline : Icons.add_circle_outline, size: 28), label: const Text(
label: Text( 'Démarrer la session',
isSessionActive ? 'Continuer la session' : 'Démarrer la session', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ),
), );
}
// MODIFICATION : Alignement sur une seule ligne (80% / 20%) avec une croix pour l'annulation
return Row(
children: [
// 80% de largeur pour continuer la session
Expanded(
flex: 8,
child: ElevatedButton.icon(
onPressed: () => _navigateToSessionSetup(context),
style: ElevatedButton.styleFrom(
backgroundColor: AppTheme.secondaryColor,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 20),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppConstants.borderRadius),
),
),
icon: const Icon(Icons.play_circle_outline, size: 28),
label: const Text(
'Continuer la session',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
),
const SizedBox(width: 12),
// 20% de largeur pour terminer/annuler la session (Bouton Croix)
Expanded(
flex: 2,
child: OutlinedButton(
onPressed: () {
// Boite de dialogue de confirmation pour éviter les erreurs
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Terminer la session ?'),
content: const Text('Êtes-vous sûr de vouloir clôturer la session en cours ?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('ANNULER'),
),
TextButton(
onPressed: () {
Navigator.pop(context);
// Clôture propre de la session dans le State global
context.read<SessionProvider>().endSession();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Session terminée avec succès !'),
backgroundColor: AppTheme.successColor,
),
);
},
child: const Text('TERMINER', style: TextStyle(color: Colors.redAccent)),
),
],
);
},
);
},
style: OutlinedButton.styleFrom(
foregroundColor: Colors.redAccent,
side: const BorderSide(color: Colors.redAccent, width: 1.5),
padding: const EdgeInsets.symmetric(vertical: 20), // Même hauteur que le bouton continuer
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppConstants.borderRadius),
),
),
child: const Icon(Icons.close, size: 28),
),
),
],
); );
} }
@@ -197,17 +276,17 @@ class _HomeScreenState extends State<HomeScreen> {
), ),
child: _recentSessions.length < 2 child: _recentSessions.length < 2
? const Center( ? const Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon(Icons.show_chart, size: 40, color: Colors.grey), Icon(Icons.show_chart, size: 40, color: Colors.grey),
Text( Text(
'Pas assez de données', 'Pas assez de données',
style: TextStyle(color: Colors.grey, fontSize: 12), style: TextStyle(color: Colors.grey, fontSize: 12),
), ),
], ],
), ),
) )
: _buildHomeTrendChart(), : _buildHomeTrendChart(),
), ),
), ),
@@ -276,7 +355,7 @@ class _HomeScreenState extends State<HomeScreen> {
final sorted = List<Session>.from(_recentSessions) final sorted = List<Session>.from(_recentSessions)
..sort((a, b) => a.createdAt.compareTo(b.createdAt)); ..sort((a, b) => a.createdAt.compareTo(b.createdAt));
final display = final display =
sorted.length > 7 ? sorted.sublist(sorted.length - 7) : sorted; sorted.length > 7 ? sorted.sublist(sorted.length - 7) : sorted;
return LineChart( return LineChart(
LineChartData( LineChartData(