first commit

This commit is contained in:
DahoudG
2025-08-20 21:00:35 +00:00
commit b2a23bdf89
583 changed files with 243074 additions and 0 deletions

View File

@@ -0,0 +1,405 @@
import 'package:flutter/material.dart';
import '../../theme/app_theme.dart';
enum BadgeType {
success,
warning,
error,
info,
neutral,
premium,
new_,
}
enum BadgeSize {
small,
medium,
large,
}
enum BadgeVariant {
filled,
outlined,
ghost,
gradient,
}
class StatusBadge extends StatelessWidget {
final String text;
final BadgeType type;
final BadgeSize size;
final BadgeVariant variant;
final IconData? icon;
final VoidCallback? onTap;
final bool animated;
final String? tooltip;
final Widget? customIcon;
final bool showPulse;
const StatusBadge({
super.key,
required this.text,
this.type = BadgeType.neutral,
this.size = BadgeSize.medium,
this.variant = BadgeVariant.filled,
this.icon,
this.onTap,
this.animated = true,
this.tooltip,
this.customIcon,
this.showPulse = false,
});
@override
Widget build(BuildContext context) {
final config = _getBadgeConfig();
Widget badge = AnimatedContainer(
duration: animated ? const Duration(milliseconds: 200) : Duration.zero,
padding: _getPadding(),
decoration: _getDecoration(config),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (icon != null || customIcon != null) ...[
_buildIcon(config),
SizedBox(width: _getIconSpacing()),
],
if (showPulse) ...[
_buildPulseIndicator(config.primaryColor),
SizedBox(width: _getIconSpacing()),
],
Text(
text,
style: _getTextStyle(config),
),
],
),
);
if (onTap != null) {
badge = Material(
color: Colors.transparent,
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(_getBorderRadius()),
child: badge,
),
);
}
if (tooltip != null) {
badge = Tooltip(
message: tooltip!,
child: badge,
);
}
return badge;
}
_BadgeConfig _getBadgeConfig() {
switch (type) {
case BadgeType.success:
return _BadgeConfig(
primaryColor: AppTheme.successColor,
backgroundColor: AppTheme.successColor.withOpacity(0.1),
borderColor: AppTheme.successColor.withOpacity(0.3),
);
case BadgeType.warning:
return _BadgeConfig(
primaryColor: AppTheme.warningColor,
backgroundColor: AppTheme.warningColor.withOpacity(0.1),
borderColor: AppTheme.warningColor.withOpacity(0.3),
);
case BadgeType.error:
return _BadgeConfig(
primaryColor: AppTheme.errorColor,
backgroundColor: AppTheme.errorColor.withOpacity(0.1),
borderColor: AppTheme.errorColor.withOpacity(0.3),
);
case BadgeType.info:
return _BadgeConfig(
primaryColor: AppTheme.infoColor,
backgroundColor: AppTheme.infoColor.withOpacity(0.1),
borderColor: AppTheme.infoColor.withOpacity(0.3),
);
case BadgeType.premium:
return _BadgeConfig(
primaryColor: const Color(0xFFFFD700),
backgroundColor: const Color(0xFFFFD700).withOpacity(0.1),
borderColor: const Color(0xFFFFD700).withOpacity(0.3),
);
case BadgeType.new_:
return _BadgeConfig(
primaryColor: const Color(0xFFFF6B6B),
backgroundColor: const Color(0xFFFF6B6B).withOpacity(0.1),
borderColor: const Color(0xFFFF6B6B).withOpacity(0.3),
);
default:
return _BadgeConfig(
primaryColor: AppTheme.textSecondary,
backgroundColor: AppTheme.textSecondary.withOpacity(0.1),
borderColor: AppTheme.textSecondary.withOpacity(0.3),
);
}
}
EdgeInsets _getPadding() {
switch (size) {
case BadgeSize.small:
return const EdgeInsets.symmetric(horizontal: 8, vertical: 2);
case BadgeSize.medium:
return const EdgeInsets.symmetric(horizontal: 12, vertical: 4);
case BadgeSize.large:
return const EdgeInsets.symmetric(horizontal: 16, vertical: 8);
}
}
double _getBorderRadius() {
switch (size) {
case BadgeSize.small:
return 12;
case BadgeSize.medium:
return 16;
case BadgeSize.large:
return 20;
}
}
double _getFontSize() {
switch (size) {
case BadgeSize.small:
return 10;
case BadgeSize.medium:
return 12;
case BadgeSize.large:
return 14;
}
}
double _getIconSize() {
switch (size) {
case BadgeSize.small:
return 12;
case BadgeSize.medium:
return 14;
case BadgeSize.large:
return 16;
}
}
double _getIconSpacing() {
switch (size) {
case BadgeSize.small:
return 4;
case BadgeSize.medium:
return 6;
case BadgeSize.large:
return 8;
}
}
Decoration _getDecoration(_BadgeConfig config) {
switch (variant) {
case BadgeVariant.filled:
return BoxDecoration(
color: config.primaryColor,
borderRadius: BorderRadius.circular(_getBorderRadius()),
boxShadow: [
BoxShadow(
color: config.primaryColor.withOpacity(0.3),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
);
case BadgeVariant.outlined:
return BoxDecoration(
color: Colors.transparent,
border: Border.all(color: config.borderColor, width: 1),
borderRadius: BorderRadius.circular(_getBorderRadius()),
);
case BadgeVariant.ghost:
return BoxDecoration(
color: config.backgroundColor,
borderRadius: BorderRadius.circular(_getBorderRadius()),
);
case BadgeVariant.gradient:
return BoxDecoration(
gradient: LinearGradient(
colors: [
config.primaryColor,
config.primaryColor.withOpacity(0.7),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(_getBorderRadius()),
boxShadow: [
BoxShadow(
color: config.primaryColor.withOpacity(0.3),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
);
}
}
TextStyle _getTextStyle(_BadgeConfig config) {
Color textColor;
switch (variant) {
case BadgeVariant.filled:
case BadgeVariant.gradient:
textColor = Colors.white;
break;
default:
textColor = config.primaryColor;
}
return TextStyle(
fontSize: _getFontSize(),
fontWeight: FontWeight.w600,
color: textColor,
letterSpacing: 0.2,
);
}
Widget _buildIcon(_BadgeConfig config) {
Color iconColor;
switch (variant) {
case BadgeVariant.filled:
case BadgeVariant.gradient:
iconColor = Colors.white;
break;
default:
iconColor = config.primaryColor;
}
if (customIcon != null) {
return customIcon!;
}
return Icon(
icon,
size: _getIconSize(),
color: iconColor,
);
}
Widget _buildPulseIndicator(Color color) {
if (!showPulse) {
return Container(
width: _getIconSize() * 0.6,
height: _getIconSize() * 0.6,
decoration: BoxDecoration(
color: color,
shape: BoxShape.circle,
),
);
}
return _PulseWidget(
size: _getIconSize() * 0.6,
color: color,
);
}
}
class _BadgeConfig {
final Color primaryColor;
final Color backgroundColor;
final Color borderColor;
_BadgeConfig({
required this.primaryColor,
required this.backgroundColor,
required this.borderColor,
});
}
// Pulse animation widget
class _PulseWidget extends StatefulWidget {
final double size;
final Color color;
const _PulseWidget({
required this.size,
required this.color,
});
@override
State<_PulseWidget> createState() => _PulseWidgetState();
}
class _PulseWidgetState extends State<_PulseWidget>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 1000),
vsync: this,
);
_animation = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut,
));
_controller.repeat(reverse: true);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return Transform.scale(
scale: 0.8 + (_animation.value * 0.4),
child: Container(
width: widget.size,
height: widget.size,
decoration: BoxDecoration(
color: widget.color.withOpacity(1.0 - _animation.value * 0.5),
shape: BoxShape.circle,
),
),
);
},
);
}
}
// Extension for easy badge creation
extension BadgeBuilder on String {
StatusBadge toBadge({
BadgeType type = BadgeType.neutral,
BadgeSize size = BadgeSize.medium,
BadgeVariant variant = BadgeVariant.filled,
IconData? icon,
VoidCallback? onTap,
}) {
return StatusBadge(
text: this,
type: type,
size: size,
variant: variant,
icon: icon,
onTap: onTap,
);
}
}