import 'package:flutter/material.dart'; import 'package:prosapp_web_app/providers/auth_provider.dart'; import 'package:prosapp_web_app/providers/professional_provider.dart'; import 'package:prosapp_web_app/providers/score_provider.dart'; import 'package:prosapp_web_app/providers/services_provider.dart'; import 'package:prosapp_web_app/providers/sidemenu_provider.dart'; import 'package:prosapp_web_app/providers/theme_provider.dart'; import 'package:prosapp_web_app/ui/shared/widgets/navbar_avatar.dart'; import 'package:provider/provider.dart'; class Navbar extends StatelessWidget { const Navbar({super.key}); @override Widget build(BuildContext context) { final size = MediaQuery.of(context).size; final professionalProvider = Provider.of(context); final themeProvider = Provider.of(context); final scoreProvider = Provider.of(context, listen: false); final isDark = themeProvider.isDark; WidgetsBinding.instance.addPostFrameCallback((_) { scoreProvider.loadReputation(context.read().user!.id); }); return Consumer(builder: (context, scoreProvider, _) { final reputation = scoreProvider.reputation; return AnimatedContainer( duration: const Duration(milliseconds: 250), width: double.infinity, height: 56, decoration: BoxDecoration( color: isDark ? const Color(0xFF1E293B) : Colors.white, boxShadow: [ BoxShadow( color: isDark ? Colors.black45 : Colors.black12, blurRadius: 6, ), ], ), child: Row( children: [ if (size.width <= 700) IconButton( icon: Icon(Icons.menu_outlined, color: isDark ? Colors.white70 : Colors.black54), onPressed: () => SideMenuProvider.openMenu(), ), const SizedBox(width: 8), const Spacer(), // Puntuación Row( children: [ Icon(Icons.star, color: Colors.amber[600], size: 16), const SizedBox(width: 3), Text( professionalProvider.isProModeActive ? reputation.averagePro.toStringAsFixed(1) : reputation.average.toStringAsFixed(1), style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: isDark ? Colors.white70 : Colors.black87, ), ), ], ), const SizedBox(width: 4), // Toggle día / noche Tooltip( message: isDark ? 'Modo día' : 'Modo noche', child: IconButton( onPressed: themeProvider.toggle, icon: AnimatedSwitcher( duration: const Duration(milliseconds: 300), transitionBuilder: (child, anim) => RotationTransition( turns: anim, child: FadeTransition(opacity: anim, child: child), ), child: Icon( isDark ? Icons.light_mode_rounded : Icons.dark_mode_rounded, key: ValueKey(isDark), color: isDark ? Colors.amber : const Color(0xFF64748B), size: 22, ), ), ), ), // Campana _NotificationBell(isDark: isDark), // Avatar const NavbarAvatar(), const SizedBox(width: 12), ], ), ); }); } } class _NotificationBell extends StatelessWidget { final bool isDark; const _NotificationBell({required this.isDark}); @override Widget build(BuildContext context) { final professionalProvider = Provider.of(context); return Consumer(builder: (context, sp, _) { final pending = sp.services .where((s) => s.service.status.index == 0) .length; return Stack( clipBehavior: Clip.none, children: [ IconButton( tooltip: 'Notificaciones', icon: AnimatedSwitcher( duration: const Duration(milliseconds: 300), child: Icon( pending > 0 ? Icons.notifications_active_rounded : Icons.notifications_outlined, key: ValueKey(pending > 0), color: pending > 0 ? const Color(0xFF42A4EF) : (isDark ? Colors.white54 : const Color(0xFF64748B)), size: 22, ), ), onPressed: () => _showSheet(context, professionalProvider.isProModeActive, sp), ), if (pending > 0) Positioned( top: 6, right: 6, child: Container( width: 16, height: 16, decoration: const BoxDecoration( color: Color(0xFFEF4444), shape: BoxShape.circle, ), child: Center( child: Text( pending > 9 ? '9+' : '$pending', style: const TextStyle( color: Colors.white, fontSize: 9, fontWeight: FontWeight.bold, ), ), ), ), ), ], ); }); } void _showSheet(BuildContext context, bool isPro, ServicesProvider sp) { final isDark = Theme.of(context).brightness == Brightness.dark; final pending = sp.services.where((s) => s.service.status.index == 0).toList(); showModalBottomSheet( context: context, backgroundColor: isDark ? const Color(0xFF1E293B) : Colors.white, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), builder: (_) => Padding( padding: const EdgeInsets.fromLTRB(20, 12, 20, 32), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Center( child: Container( width: 36, height: 4, decoration: BoxDecoration( color: Colors.grey[400], borderRadius: BorderRadius.circular(2), ), ), ), const SizedBox(height: 16), Row( children: [ Icon(Icons.notifications_outlined, size: 20, color: isDark ? Colors.white70 : Colors.black87), const SizedBox(width: 8), Text('Notificaciones', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: isDark ? Colors.white : Colors.black87, )), const Spacer(), if (pending.isNotEmpty) Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration( color: const Color(0xFF42A4EF), borderRadius: BorderRadius.circular(10), ), child: Text('${pending.length} nuevas', style: const TextStyle(color: Colors.white, fontSize: 11)), ), ], ), const SizedBox(height: 12), if (pending.isEmpty) Padding( padding: const EdgeInsets.symmetric(vertical: 28), child: Center( child: Column(children: [ Icon(Icons.notifications_none, size: 48, color: Colors.grey[400]), const SizedBox(height: 8), Text('Sin notificaciones pendientes', style: TextStyle(color: Colors.grey[500])), ]), ), ) else ...pending.take(5).map((s) => ListTile( contentPadding: EdgeInsets.zero, leading: Container( width: 40, height: 40, decoration: BoxDecoration( color: const Color(0xFF42A4EF).withOpacity(0.12), shape: BoxShape.circle, ), child: const Icon(Icons.room_service_outlined, color: Color(0xFF42A4EF), size: 20), ), title: Text( isPro ? 'Nueva solicitud de servicio' : 'Servicio pendiente', style: TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: isDark ? Colors.white : Colors.black87, ), ), subtitle: Text( s.service.address.isNotEmpty ? s.service.address : 'Sin dirección', style: TextStyle( fontSize: 12, color: isDark ? Colors.white54 : Colors.black54, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), trailing: const Icon(Icons.circle, color: Color(0xFF42A4EF), size: 8), )), ], ), ), ); } }