import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:image_picker/image_picker.dart'; import 'package:pshared/provider/account.dart'; import 'package:pweb/widgets/drawer/avatar.dart'; class AvatarTile extends StatefulWidget { final String? avatarUrl; final String title; final String description; final String errorText; const AvatarTile({ super.key, required this.avatarUrl, required this.title, required this.description, required this.errorText, }); @override State createState() => _AvatarTileState(); } class _AvatarTileState extends State { static const double _avatarSize = 96.0; static const double _iconSize = 32.0; static const double _titleSpacing = 4.0; bool _isHovering = false; bool _isUploading = false; String _errorText = ''; Future _pickImage(AccountProvider provider) async { if (_isUploading) return; final picker = ImagePicker(); final file = await picker.pickImage(source: ImageSource.gallery); if (file == null) return; setState(() { _isUploading = true; _errorText = ''; }); try { await provider.uploadAvatar(file); } catch (_) { if (!mounted) return; setState(() => _errorText = widget.errorText); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(widget.errorText)), ); } finally { if (mounted) { setState(() => _isUploading = false); } } } @override Widget build(BuildContext context) { return Consumer( builder: (context, provider, _) { final theme = Theme.of(context); final isBusy = _isUploading || provider.isLoading; return Column( children: [ MouseRegion( onEnter: (_) => setState(() => _isHovering = true), onExit: (_) => setState(() => _isHovering = false), child: GestureDetector( onTap: isBusy ? null : () => _pickImage(provider), child: Stack( alignment: Alignment.center, children: [ AccountAvatar( size: _avatarSize, showHeader: false, provider: provider, fallbackUrl: widget.avatarUrl, ), if (_isHovering || _isUploading) ClipOval( child: Container( width: _avatarSize, height: _avatarSize, color: theme.colorScheme.primary.withAlpha(90), child: _isUploading ? SizedBox( width: _iconSize, height: _iconSize, child: CircularProgressIndicator( strokeWidth: 3, valueColor: AlwaysStoppedAnimation(theme.colorScheme.onSecondary), ), ) : Icon( Icons.camera_alt, color: theme.colorScheme.onSecondary, size: _iconSize, ), ), ), ], ), ), ), SizedBox(height: _titleSpacing), Text( widget.description, style: theme.textTheme.bodySmall?.copyWith( color: theme.colorScheme.onSecondary, ), ), if (_errorText.isNotEmpty) ...[ SizedBox(height: _titleSpacing), Text( _errorText, style: theme.textTheme.bodySmall?.copyWith( color: theme.colorScheme.error, ), ), ], ], ); }, ); } }