Restructuration majeure du projet: migration de flutt vers app, ajout de l'API et mise à jour du site web

This commit is contained in:
d6soft
2025-05-16 09:19:03 +02:00
parent b5aafc424b
commit 5c2620de30
391 changed files with 19780 additions and 7233 deletions

View File

@@ -0,0 +1,199 @@
import 'package:flutter/material.dart';
import 'dart:ui';
/// Widget d'overlay de chargement amélioré qui affiche une barre de progression
/// avec un effet de flou sur l'arrière-plan et un message détaillé sur l'étape en cours
class LoadingProgressOverlay extends StatefulWidget {
final String? message;
final double progress;
final String? stepDescription;
final Color backgroundColor;
final Color progressColor;
final Color textColor;
final double blurAmount;
final bool showPercentage;
const LoadingProgressOverlay({
Key? key,
this.message,
required this.progress,
this.stepDescription,
this.backgroundColor = Colors.black54,
this.progressColor = Colors.white,
this.textColor = Colors.white,
this.blurAmount = 5.0,
this.showPercentage = true,
}) : super(key: key);
@override
State<LoadingProgressOverlay> createState() => _LoadingProgressOverlayState();
}
class _LoadingProgressOverlayState extends State<LoadingProgressOverlay>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> _progressAnimation;
@override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 300),
);
_progressAnimation = Tween<double>(begin: 0, end: widget.progress).animate(
CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
);
_animationController.forward();
}
@override
void didUpdateWidget(LoadingProgressOverlay oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.progress != widget.progress) {
_progressAnimation = Tween<double>(
begin: oldWidget.progress,
end: widget.progress,
).animate(
CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
);
_animationController.reset();
_animationController.forward();
}
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BackdropFilter(
filter: ImageFilter.blur(
sigmaX: widget.blurAmount, sigmaY: widget.blurAmount),
child: Container(
color: widget.backgroundColor,
child: Center(
child: Container(
width: MediaQuery.of(context).size.width * 0.85,
padding: const EdgeInsets.all(30),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.9),
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: Colors.black45,
blurRadius: 15,
spreadRadius: 5,
offset: const Offset(0, 5),
),
],
border: Border.all(
color: Colors.white.withOpacity(0.1),
width: 1.5,
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
if (widget.message != null) ...[
Text(
widget.message!,
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: widget.textColor,
letterSpacing: 0.5,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 24),
],
AnimatedBuilder(
animation: _progressAnimation,
builder: (context, child) {
return Column(
children: [
LinearProgressIndicator(
value: _progressAnimation.value,
backgroundColor:
widget.progressColor.withOpacity(0.3),
valueColor: AlwaysStoppedAnimation<Color>(
widget.progressColor),
minHeight: 15,
borderRadius: BorderRadius.circular(8),
),
if (widget.showPercentage) ...[
const SizedBox(height: 8),
Text(
'${(_progressAnimation.value * 100).toInt()}%',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: widget.textColor,
letterSpacing: 1.2,
),
),
],
],
);
},
),
if (widget.stepDescription != null) ...[
const SizedBox(height: 16),
Text(
widget.stepDescription!,
style: TextStyle(
fontSize: 16,
color: widget.textColor.withOpacity(0.9),
fontStyle: FontStyle.italic,
),
textAlign: TextAlign.center,
),
],
],
),
),
),
),
);
}
}
/// Classe utilitaire pour gérer l'overlay de chargement avec progression
class LoadingProgressOverlayUtils {
/// Méthode pour afficher l'overlay de chargement avec progression
static OverlayEntry show({
required BuildContext context,
String? message,
double progress = 0.0,
String? stepDescription,
double blurAmount = 5.0,
bool showPercentage = true,
}) {
final overlayEntry = OverlayEntry(
builder: (context) => LoadingProgressOverlay(
message: message,
progress: progress,
stepDescription: stepDescription,
blurAmount: blurAmount,
showPercentage: showPercentage,
),
);
Overlay.of(context).insert(overlayEntry);
return overlayEntry;
}
/// Méthode pour mettre à jour l'overlay existant
static void update({
required OverlayEntry overlayEntry,
String? message,
required double progress,
String? stepDescription,
}) {
overlayEntry.markNeedsBuild();
}
}