import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:image_picker/image_picker.dart'; import 'dart:io'; import 'package:kzeduca_app/services/user_state_service.dart'; import 'package:kzeduca_app/services/i18n_service.dart'; // Importe a tela de login para navegação import 'package:kzeduca_app/screens/auth_screen.dart'; class UserProfileScreen extends StatefulWidget { const UserProfileScreen({super.key}); @override State createState() => _UserProfileScreenState(); } class _UserProfileScreenState extends State { final _formKey = GlobalKey(); late TextEditingController _nameController; XFile? _profileImage; // Dados simulados para o gráfico. Em um app real, eles viriam do backend. List _userTransactions = [150.0, 200.0, 300.0, 450.0]; @override void initState() { super.initState(); final user = Provider.of(context, listen: false).currentUser; _nameController = TextEditingController(text: user?.username ?? ''); } @override void dispose() { _nameController.dispose(); super.dispose(); } Future _pickImage() async { final pickedFile = await ImagePicker().pickImage(source: ImageSource.gallery); if (pickedFile != null) { setState(() { _profileImage = pickedFile; }); } } void _saveProfile() async { if (_formKey.currentState!.validate()) { final userState = Provider.of(context, listen: false); final i18n = Provider.of(context, listen: false); try { await userState.updateUserProfile( username: _nameController.text, profileImage: _profileImage, ); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(i18n.t('profile_updated')), backgroundColor: Colors.purple.shade400, ), ); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Falha ao atualizar o perfil: $e'), backgroundColor: Colors.red, ), ); } } } void _logout() { Provider.of(context, listen: false).logout(); Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute(builder: (context) => const AuthScreen()), (Route route) => false, ); } @override Widget build(BuildContext context) { final i18n = Provider.of(context); final userState = Provider.of(context); final user = userState.currentUser; if (user == null) { return const Center(child: CircularProgressIndicator()); } final double balance = user.currentBalance; // Adiciona o saldo atual à lista para o gráfico List savingsHistory = List.from(_userTransactions)..add(balance); // Calcula o valor máximo para o eixo Y do gráfico, evitando o erro em listas vazias double maxYValue = 100.0; if (savingsHistory.isNotEmpty) { maxYValue = (savingsHistory.reduce((a, b) => a > b ? a : b) * 1.2).clamp(100.0, double.infinity); } final List<_BadgeData> badges = [ if (balance >= 1000) _BadgeData(icon: Icons.star, label: i18n.t('super_saver'), color: Colors.amber), // Adicione mais badges aqui, se necessário. ]; return Scaffold( backgroundColor: const Color(0xFF1A1A2E), // Fundo escuro appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, title: Text(i18n.t('profile'), style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold)), iconTheme: const IconThemeData(color: Colors.white), ), body: LayoutBuilder( builder: (context, constraints) => SingleChildScrollView( padding: const EdgeInsets.all(24), child: Center( child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 500), child: Form( key: _formKey, child: Column( children: [ // Avatar com botão de editar Stack( children: [ Container( width: 120, height: 120, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all(color: Colors.purple.shade400, width: 3), boxShadow: [ BoxShadow( color: Colors.purple.shade400.withOpacity(0.4), blurRadius: 10, spreadRadius: 3, ), ], ), child: CircleAvatar( radius: 56, backgroundColor: const Color(0xFF2E2E4E), backgroundImage: _profileImage != null ? FileImage(File(_profileImage!.path)) : (user.profileImageUrl != null ? NetworkImage(user.profileImageUrl!) as ImageProvider? : null), child: _profileImage == null && user.profileImageUrl == null ? Icon(Icons.person, size: 60, color: Colors.white.withOpacity(0.9)) : null, ), ), Positioned( bottom: 0, right: 4, child: GestureDetector( onTap: _pickImage, child: Container( decoration: BoxDecoration( color: const Color(0xFF8A2BE2), shape: BoxShape.circle, border: Border.all(color: Colors.white, width: 2), ), padding: const EdgeInsets.all(8), child: const Icon(Icons.edit, size: 18, color: Colors.white), ), ), ), ], ), const SizedBox(height: 16), // Badges if (badges.isNotEmpty) Wrap( spacing: 12, children: badges.map((b) => _Badge(b)).toList(), ), const SizedBox(height: 24), // Gráfico de barras Container( height: 220, padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: const Color(0xFF2E2E4E).withOpacity(0.8), borderRadius: BorderRadius.circular(20), border: Border.all(color: Colors.purple.shade400, width: 1), ), child: BarChart( BarChartData( alignment: BarChartAlignment.spaceAround, maxY: maxYValue, barTouchData: BarTouchData(enabled: false), titlesData: FlTitlesData( leftTitles: AxisTitles( sideTitles: SideTitles(showTitles: false), ), rightTitles: AxisTitles( sideTitles: SideTitles(showTitles: false), ), topTitles: AxisTitles( sideTitles: SideTitles(showTitles: false), ), bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, // === INÍCIO DA CORREÇÃO FL_CHART === getTitlesWidget: (value, meta) { final List labels = ['Mês 1', 'Mês 2', 'Mês 3', 'Mês 4', 'Atual']; final String title = labels[value.toInt() % labels.length]; // Retorna o Text diretamente com um Padding para espaçamento return Padding( padding: const EdgeInsets.only(top: 4.0), child: Text( title, style: const TextStyle(color: Colors.white70, fontSize: 10), ), ); }, // === FIM DA CORREÇÃO FL_CHART === reservedSize: 28, ), ), ), gridData: FlGridData( show: true, drawVerticalLine: false, horizontalInterval: 20, getDrawingHorizontalLine: (value) => FlLine( color: Colors.white.withOpacity(0.1), strokeWidth: 1, ), ), borderData: FlBorderData(show: false), barGroups: List.generate( savingsHistory.length, (i) => BarChartGroupData( x: i, barRods: [ BarChartRodData( toY: savingsHistory[i], color: i == savingsHistory.length - 1 ? Colors.cyanAccent : Colors.purple.shade400, width: 16, borderRadius: BorderRadius.circular(6), ), ], ), ), ), ), ), const SizedBox(height: 32), // Campos do perfil _ProfileField( icon: Icons.person_outline, label: i18n.t('name'), controller: _nameController, validator: (v) => v == null || v.isEmpty ? i18n.t('required_field') : null, ), const SizedBox(height: 16), _ProfileField( icon: Icons.email_outlined, label: i18n.t('email'), initialValue: user.email, enabled: false, ), const SizedBox(height: 16), _ProfileField( icon: Icons.badge_outlined, label: i18n.t('user_id'), initialValue: user.uid, enabled: false, ), const SizedBox(height: 16), _ProfileField( icon: Icons.account_balance_wallet_outlined, label: i18n.t('balance'), initialValue: balance.toStringAsFixed(2), enabled: false, ), const SizedBox(height: 32), Row( children: [ Expanded( child: _GradientButton( label: i18n.t('save'), icon: Icons.save_outlined, onPressed: _saveProfile, ), ), const SizedBox(width: 16), _IconButton( icon: Icons.logout, tooltip: i18n.t('logout'), onPressed: _logout, color: Colors.redAccent.shade400, ), ], ), ], ), ), ), ), ), ), ); } } class _ProfileField extends StatelessWidget { final IconData icon; final String label; final TextEditingController? controller; final String? initialValue; final bool enabled; final TextInputType? keyboardType; final String? Function(String?)? validator; const _ProfileField({ required this.icon, required this.label, this.controller, this.initialValue, this.enabled = true, this.keyboardType, this.validator, }); @override Widget build(BuildContext context) { return TextFormField( controller: controller, initialValue: initialValue, enabled: enabled, keyboardType: keyboardType, validator: validator, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w400), decoration: InputDecoration( prefixIcon: Icon(icon, color: Colors.purple.shade300), filled: true, fillColor: Colors.white.withOpacity(0.05), labelText: label, labelStyle: const TextStyle(color: Colors.white70), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.purple.shade200, width: 1), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.purple.shade200.withOpacity(0.3), width: 1), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.cyanAccent.shade400, width: 2), ), disabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.grey.withOpacity(0.2), width: 1), ), ), ); } } class _BadgeData { final IconData icon; final String label; final Color color; _BadgeData({required this.icon, required this.label, required this.color}); } class _Badge extends StatelessWidget { final _BadgeData data; const _Badge(this.data); @override Widget build(BuildContext context) { return Chip( avatar: Icon(data.icon, color: Colors.white, size: 18), label: Text(data.label, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold)), backgroundColor: data.color, padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), elevation: 2, shadowColor: Colors.black26, ); } } class _GradientButton extends StatelessWidget { final String label; final IconData icon; final VoidCallback onPressed; const _GradientButton({ required this.label, required this.icon, required this.onPressed, }); @override Widget build(BuildContext context) { return ElevatedButton( onPressed: onPressed, style: ElevatedButton.styleFrom( padding: const EdgeInsets.all(0), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), elevation: 8, ), child: Ink( decoration: BoxDecoration( gradient: const LinearGradient( colors: [Color(0xFF8A2BE2), Color(0xFF6A1B9A)], begin: Alignment.centerLeft, end: Alignment.centerRight, ), borderRadius: BorderRadius.circular(12), ), child: Container( constraints: const BoxConstraints(minHeight: 50), alignment: Alignment.center, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(icon, color: Colors.white), const SizedBox(width: 8), Text( label, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold), ), ], ), ), ), ); } } class _IconButton extends StatelessWidget { final IconData icon; final String tooltip; final VoidCallback onPressed; final Color color; const _IconButton({ required this.icon, required this.tooltip, required this.onPressed, required this.color, }); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(12), border: Border.all(color: color.withOpacity(0.5), width: 1), ), child: IconButton( icon: Icon(icon, color: color), tooltip: tooltip, onPressed: onPressed, ), ); } }