import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:prosapp_web_app/models/schedules_entity.dart'; import 'package:prosapp_web_app/models/service.dart'; import 'package:prosapp_web_app/models/service_status.dart'; import 'package:prosapp_web_app/models/servicio_profesional.dart'; import 'package:prosapp_web_app/providers/auth_provider.dart'; import 'package:prosapp_web_app/providers/services_provider.dart'; import 'package:prosapp_web_app/providers/theme_provider.dart'; import 'package:prosapp_web_app/services/navigation_service.dart'; import 'package:provider/provider.dart'; class ServicesView extends StatelessWidget { final String type; const ServicesView({super.key, required this.type}); @override Widget build(BuildContext context) { final servicesProvider = Provider.of(context, listen: false); final userId = Provider.of(context, listen: false).user!.id; if (type == 'user') servicesProvider.getServicesForUser(userId); if (type == 'professional') servicesProvider.getServicesForProfessional(userId); final isDark = context.watch().isDark; return Center( child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 900), child: Consumer( builder: (context, sp, _) { if (sp.isLoading) { return const Center(child: CircularProgressIndicator()); } if (sp.services.isEmpty) { return _EmptyState( isDark: isDark, icon: Icons.room_service_outlined, title: 'Sin servicios activos', subtitle: 'Aquí verás tus servicios en curso.', ); } return ListView.builder( padding: const EdgeInsets.symmetric(vertical: 8), itemCount: sp.services.length, itemBuilder: (context, i) { final data = sp.services[i]; return _ServiceCard( data: data, isDark: isDark, onTap: () => NavigationService.replaceTo( '/dashboard/$type/service/${data.service.id}'), statusWidget: _activeStatus(data.service, isDark), ); }, ); }, ), ), ); } Widget _activeStatus(Service service, bool isDark) { switch (service.status) { case ServiceStatus.pending: return _StatusBadge(label: 'Pendiente', color: const Color(0xFFF59E0B)); case ServiceStatus.acepted: return _StatusBadge(label: 'Aceptado', color: const Color(0xFF10B981)); case ServiceStatus.active: return _StatusBadge(label: 'En curso', color: const Color(0xFF3B82F6)); default: return const SizedBox(); } } } // ── Shared widgets ──────────────────────────────────────────────────────────── class _ServiceCard extends StatelessWidget { final ServicioProfesional data; final bool isDark; final VoidCallback onTap; final Widget statusWidget; const _ServiceCard({ required this.data, required this.isDark, required this.onTap, required this.statusWidget, }); @override Widget build(BuildContext context) { final cardBg = isDark ? const Color(0xFF1E293B) : Colors.white; final border = isDark ? const Color(0xFF334155) : const Color(0xFFE5E7EB); final textPrimary = isDark ? Colors.white : const Color(0xFF111827); final textSecondary = isDark ? const Color(0xFF94A3B8) : const Color(0xFF6B7280); final hasPic = data.user.picture != null && data.user.picture!.isNotEmpty; final day = DateTime.tryParse(data.service.day); final dateStr = day != null ? DateFormat('dd MMM yyyy', 'es').format(day) : data.service.day; final timeStr = ScheduleEntity.getFormatTime(data.service.range1Hour1) ?? ''; return Padding( padding: const EdgeInsets.only(bottom: 10), child: Material( color: cardBg, borderRadius: BorderRadius.circular(14), child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(14), child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(14), border: Border.all(color: border), ), child: Row( children: [ // Avatar Container( width: 56, height: 56, decoration: BoxDecoration( shape: BoxShape.circle, color: const Color(0xFF42A4EF).withOpacity(0.15), ), child: ClipOval( child: hasPic ? FadeInImage.assetNetwork( placeholder: 'loader.gif', image: data.user.picture!, fit: BoxFit.cover, ) : Center( child: Text( data.user.name.isNotEmpty ? data.user.name[0].toUpperCase() : '?', style: const TextStyle( color: Color(0xFF42A4EF), fontSize: 22, fontWeight: FontWeight.bold, ), ), ), ), ), const SizedBox(width: 14), // Info Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(data.user.name, style: TextStyle( fontSize: 15, fontWeight: FontWeight.w600, color: textPrimary, )), if (data.service.address.isNotEmpty) ...[ const SizedBox(height: 3), Row( children: [ Icon(Icons.location_on_outlined, size: 13, color: textSecondary), const SizedBox(width: 3), Expanded( child: Text( data.service.address, style: TextStyle(fontSize: 12, color: textSecondary), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], ), ], const SizedBox(height: 6), Row( children: [ Icon(Icons.calendar_today_outlined, size: 13, color: textSecondary), const SizedBox(width: 4), Text('$timeStr · $dateStr', style: TextStyle(fontSize: 12, color: textSecondary)), ], ), ], ), ), const SizedBox(width: 10), // Status + arrow Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ statusWidget, const SizedBox(height: 8), Icon(Icons.chevron_right, color: textSecondary, size: 18), ], ), ], ), ), ), ), ); } } class _StatusBadge extends StatelessWidget { final String label; final Color color; const _StatusBadge({required this.label, required this.color}); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration( color: color.withOpacity(0.12), borderRadius: BorderRadius.circular(20), border: Border.all(color: color.withOpacity(0.4)), ), child: Text(label, style: TextStyle( fontSize: 11, fontWeight: FontWeight.w600, color: color, )), ); } } class _EmptyState extends StatelessWidget { final bool isDark; final IconData icon; final String title; final String subtitle; const _EmptyState({ required this.isDark, required this.icon, required this.title, required this.subtitle, }); @override Widget build(BuildContext context) { final textPrimary = isDark ? Colors.white : const Color(0xFF111827); final textSecondary = isDark ? const Color(0xFF94A3B8) : const Color(0xFF6B7280); return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(icon, size: 64, color: textSecondary.withOpacity(0.5)), const SizedBox(height: 16), Text(title, style: TextStyle( fontSize: 17, fontWeight: FontWeight.w600, color: textPrimary)), const SizedBox(height: 6), Text(subtitle, style: TextStyle(fontSize: 13, color: textSecondary)), ], ), ); } }