import 'package:flutter/material.dart'; import '../../theme/app_theme.dart'; import '../badges/status_badge.dart'; import '../badges/count_badge.dart'; enum AvatarSize { tiny, small, medium, large, extraLarge, } enum AvatarShape { circle, rounded, square, } enum AvatarVariant { standard, gradient, outlined, glass, } class SophisticatedAvatar extends StatefulWidget { final String? imageUrl; final String? initials; final IconData? icon; final AvatarSize size; final AvatarShape shape; final AvatarVariant variant; final Color? backgroundColor; final Color? foregroundColor; final Gradient? gradient; final VoidCallback? onTap; final Widget? badge; final bool showOnlineStatus; final bool isOnline; final Widget? overlay; final bool animated; final List? customShadow; final Border? border; const SophisticatedAvatar({ super.key, this.imageUrl, this.initials, this.icon, this.size = AvatarSize.medium, this.shape = AvatarShape.circle, this.variant = AvatarVariant.standard, this.backgroundColor, this.foregroundColor, this.gradient, this.onTap, this.badge, this.showOnlineStatus = false, this.isOnline = false, this.overlay, this.animated = true, this.customShadow, this.border, }); @override State createState() => _SophisticatedAvatarState(); } class _SophisticatedAvatarState extends State with SingleTickerProviderStateMixin { late AnimationController _animationController; late Animation _scaleAnimation; late Animation _rotationAnimation; @override void initState() { super.initState(); _animationController = AnimationController( duration: const Duration(milliseconds: 300), vsync: this, ); _scaleAnimation = Tween( begin: 1.0, end: 0.95, ).animate(CurvedAnimation( parent: _animationController, curve: Curves.easeInOut, )); _rotationAnimation = Tween( begin: 0.0, end: 0.1, ).animate(CurvedAnimation( parent: _animationController, curve: Curves.easeInOut, )); } @override void dispose() { _animationController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final size = _getSize(); final borderRadius = _getBorderRadius(size); Widget avatar = AnimatedBuilder( animation: _animationController, builder: (context, child) { return Transform.scale( scale: widget.animated ? _scaleAnimation.value : 1.0, child: Transform.rotate( angle: widget.animated ? _rotationAnimation.value : 0.0, child: Container( width: size, height: size, decoration: _getDecoration(size, borderRadius), child: ClipRRect( borderRadius: borderRadius, child: Stack( fit: StackFit.expand, children: [ _buildContent(), if (widget.overlay != null) widget.overlay!, ], ), ), ), ), ); }, ); // Wrap with gesture detector if onTap is provided if (widget.onTap != null) { avatar = GestureDetector( onTap: widget.onTap, onTapDown: widget.animated ? (_) => _animationController.forward() : null, onTapUp: widget.animated ? (_) => _animationController.reverse() : null, onTapCancel: widget.animated ? () => _animationController.reverse() : null, child: avatar, ); } // Add badges and status indicators return Stack( clipBehavior: Clip.none, children: [ avatar, // Online status indicator if (widget.showOnlineStatus) Positioned( bottom: size * 0.05, right: size * 0.05, child: Container( width: size * 0.25, height: size * 0.25, decoration: BoxDecoration( color: widget.isOnline ? AppTheme.successColor : AppTheme.textHint, shape: BoxShape.circle, border: Border.all( color: Colors.white, width: size * 0.02, ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 4, offset: const Offset(0, 2), ), ], ), ), ), // Custom badge if (widget.badge != null) Positioned( top: -size * 0.1, right: -size * 0.1, child: widget.badge!, ), ], ); } double _getSize() { switch (widget.size) { case AvatarSize.tiny: return 24; case AvatarSize.small: return 32; case AvatarSize.medium: return 48; case AvatarSize.large: return 64; case AvatarSize.extraLarge: return 96; } } BorderRadius _getBorderRadius(double size) { switch (widget.shape) { case AvatarShape.circle: return BorderRadius.circular(size / 2); case AvatarShape.rounded: return BorderRadius.circular(size * 0.2); case AvatarShape.square: return BorderRadius.zero; } } double _getFontSize() { switch (widget.size) { case AvatarSize.tiny: return 10; case AvatarSize.small: return 12; case AvatarSize.medium: return 18; case AvatarSize.large: return 24; case AvatarSize.extraLarge: return 36; } } double _getIconSize() { switch (widget.size) { case AvatarSize.tiny: return 12; case AvatarSize.small: return 16; case AvatarSize.medium: return 24; case AvatarSize.large: return 32; case AvatarSize.extraLarge: return 48; } } Decoration _getDecoration(double size, BorderRadius borderRadius) { switch (widget.variant) { case AvatarVariant.standard: return BoxDecoration( color: widget.backgroundColor ?? AppTheme.primaryColor, borderRadius: borderRadius, border: widget.border, boxShadow: widget.customShadow ?? [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 8, offset: const Offset(0, 4), ), ], ); case AvatarVariant.gradient: return BoxDecoration( gradient: widget.gradient ?? LinearGradient( colors: [ widget.backgroundColor ?? AppTheme.primaryColor, (widget.backgroundColor ?? AppTheme.primaryColor).withOpacity(0.7), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: borderRadius, border: widget.border, boxShadow: [ BoxShadow( color: (widget.backgroundColor ?? AppTheme.primaryColor) .withOpacity(0.3), blurRadius: 12, offset: const Offset(0, 6), ), ], ); case AvatarVariant.outlined: return BoxDecoration( color: Colors.transparent, borderRadius: borderRadius, border: widget.border ?? Border.all( color: widget.backgroundColor ?? AppTheme.primaryColor, width: 2, ), ); case AvatarVariant.glass: return BoxDecoration( color: (widget.backgroundColor ?? Colors.white).withOpacity(0.2), borderRadius: borderRadius, border: Border.all( color: Colors.white.withOpacity(0.3), width: 1, ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 20, offset: const Offset(0, 8), ), ], ); } } Widget _buildContent() { final foregroundColor = widget.foregroundColor ?? Colors.white; if (widget.imageUrl != null && widget.imageUrl!.isNotEmpty) { return Image.network( widget.imageUrl!, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) => _buildFallback(foregroundColor), ); } return _buildFallback(foregroundColor); } Widget _buildFallback(Color foregroundColor) { if (widget.initials != null && widget.initials!.isNotEmpty) { return Center( child: Text( widget.initials!.toUpperCase(), style: TextStyle( color: foregroundColor, fontSize: _getFontSize(), fontWeight: FontWeight.bold, ), ), ); } if (widget.icon != null) { return Center( child: Icon( widget.icon, color: foregroundColor, size: _getIconSize(), ), ); } return Center( child: Icon( Icons.person, color: foregroundColor, size: _getIconSize(), ), ); } } // Predefined avatar variants class CircleAvatar extends SophisticatedAvatar { const CircleAvatar({ super.key, super.imageUrl, super.initials, super.icon, super.size, super.backgroundColor, super.foregroundColor, super.onTap, super.badge, super.showOnlineStatus, super.isOnline, }) : super(shape: AvatarShape.circle); } class RoundedAvatar extends SophisticatedAvatar { const RoundedAvatar({ super.key, super.imageUrl, super.initials, super.icon, super.size, super.backgroundColor, super.foregroundColor, super.onTap, super.badge, }) : super(shape: AvatarShape.rounded); } class GradientAvatar extends SophisticatedAvatar { const GradientAvatar({ super.key, super.imageUrl, super.initials, super.icon, super.size, super.gradient, super.onTap, super.badge, super.showOnlineStatus, super.isOnline, }) : super(variant: AvatarVariant.gradient); }