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 StatefulWidget { const Navbar({super.key}); @override State createState() => _NavbarState(); } class _NavbarState extends State { @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { final userId = context.read().user?.id; if (userId != null) { context.read().loadReputation(userId); } }); } @override Widget build(BuildContext context) { final size = MediaQuery.of(context).size; final themeProvider = context.watch(); final isDark = themeProvider.isDark; final scoreProvider = context.watch(); final professionalProvider = context.watch(); final servicesProvider = context.watch(); final iconColor = isDark ? Colors.white70 : const Color(0xFF475569); final bgColor = isDark ? const Color(0xFF1E293B) : Colors.white; final hoverColor = isDark ? Colors.white.withOpacity(0.10) : const Color(0xFF42A4EF).withOpacity(0.10); final overlayColor = WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.hovered)) return hoverColor; if (states.contains(WidgetState.pressed)) return hoverColor.withOpacity(0.2); return Colors.transparent; }); final reputation = scoreProvider.reputation; final pendingCount = servicesProvider.services.where((s) => s.service.status.index == 0).length; return Container( width: double.infinity, height: 56, decoration: BoxDecoration( color: bgColor, boxShadow: [ BoxShadow( color: isDark ? Colors.black54 : Colors.black12, blurRadius: 6, ), ], ), child: Row( children: [ if (size.width <= 700) IconButton( icon: Icon(Icons.menu, color: iconColor, size: 22), style: IconButton.styleFrom(overlayColor: hoverColor), onPressed: SideMenuProvider.openMenu, ), const Spacer(), // Puntuación Icon(Icons.star_rounded, color: Colors.amber, size: 16), const SizedBox(width: 3), Text( (professionalProvider.isProModeActive ? reputation.averagePro : reputation.average) .toStringAsFixed(1), style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: isDark ? Colors.white : const Color(0xFF1E293B), ), ), const SizedBox(width: 6), // Toggle día/noche IconButton( tooltip: isDark ? 'Modo día' : 'Modo noche', style: IconButton.styleFrom(overlayColor: hoverColor), icon: Icon( isDark ? Icons.light_mode : Icons.dark_mode, color: isDark ? Colors.amber : iconColor, size: 22, ), onPressed: themeProvider.toggle, ), // Campana Stack( clipBehavior: Clip.none, children: [ IconButton( tooltip: 'Notificaciones', style: IconButton.styleFrom(overlayColor: hoverColor), icon: Icon( pendingCount > 0 ? Icons.notifications_active : Icons.notifications_outlined, color: pendingCount > 0 ? const Color(0xFF42A4EF) : iconColor, size: 22, ), onPressed: () => _showNotifications( context, servicesProvider, professionalProvider.isProModeActive, isDark, ), ), if (pendingCount > 0) Positioned( top: 6, right: 6, child: Container( width: 15, height: 15, decoration: const BoxDecoration( color: Color(0xFFEF4444), shape: BoxShape.circle, ), child: Center( child: Text( pendingCount > 9 ? '9+' : '$pendingCount', style: const TextStyle( color: Colors.white, fontSize: 8, fontWeight: FontWeight.bold, ), ), ), ), ), ], ), const SizedBox(width: 4), const NavbarAvatar(), const SizedBox(width: 12), ], ), ); } void _showNotifications( BuildContext context, ServicesProvider sp, bool isPro, bool isDark, ) { 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), )), ], ), ), ); } }