import 'package:flutter/material.dart'; import '../../../../core/theme/app_colors.dart'; import '../../data/models/dashboard_metrics_model.dart'; class DashboardMetricsCards extends StatelessWidget { final DashboardMetricsModel metrics; const DashboardMetricsCards({super.key, required this.metrics}); String _formatNumber(int n) { return n.toString().replaceAllMapped( RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'), (Match m) => '${m[1]},', ); } @override Widget build(BuildContext context) { final cards = [ // 1. Total de Nuevos Pacientes _buildMetricCard( title: 'Total Nuevos Pacientes', value: _formatNumber(metrics.nuevosPacientes), subtitle: 'Registrados en la plataforma', icon: Icons.person_add_alt_1_rounded, iconColor: AppColors.primary, bgColor: AppColors.primaryContainer, ), // 2. Total de Consultados Hoy _buildMetricCard( title: 'Total Consultados Hoy', value: _formatNumber(metrics.consultadosHoy), subtitle: 'Atenciones médicas realizadas', icon: Icons.assignment_turned_in_rounded, iconColor: AppColors.teal, bgColor: AppColors.teal.withValues(alpha: 0.12), ), // 3. Total de Citas para Hoy _buildMetricCard( title: 'Total Citas para Hoy', value: _formatNumber(metrics.citasHoy), subtitle: 'Pacientes agendados', icon: Icons.event_available_rounded, iconColor: AppColors.warning, bgColor: AppColors.warning.withValues(alpha: 0.12), ), // 4. Total de Pacientes por Sexo _buildGenderCard(), ]; return LayoutBuilder( builder: (context, constraints) { const spacing = 16.0; // Distribución equitativa en 4 columnas (pantallas amplias) if (constraints.maxWidth >= 1000) { return IntrinsicHeight( child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Expanded(child: cards[0]), const SizedBox(width: spacing), Expanded(child: cards[1]), const SizedBox(width: spacing), Expanded(child: cards[2]), const SizedBox(width: spacing), Expanded(child: cards[3]), ], ), ); } // Distribución equitativa en 2 columnas (pantallas medianas) if (constraints.maxWidth >= 550) { return Column( children: [ IntrinsicHeight( child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Expanded(child: cards[0]), const SizedBox(width: spacing), Expanded(child: cards[1]), ], ), ), const SizedBox(height: spacing), IntrinsicHeight( child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Expanded(child: cards[2]), const SizedBox(width: spacing), Expanded(child: cards[3]), ], ), ), ], ); } // 1 columna ocupando 100% del ancho (pantallas móviles / compactas) return Column( children: [ cards[0], const SizedBox(height: spacing), cards[1], const SizedBox(height: spacing), cards[2], const SizedBox(height: spacing), cards[3], ], ); }, ); } Widget _buildMetricCard({ required String title, String? value, Widget? valueWidget, required String subtitle, required IconData icon, required Color iconColor, required Color bgColor, }) { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(14), border: Border.all(color: AppColors.border), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.02), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: bgColor, borderRadius: BorderRadius.circular(12), ), child: Icon(icon, color: iconColor, size: 24), ), const SizedBox(width: 14), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( title, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: AppColors.textSecondary, ), ), const SizedBox(height: 4), valueWidget ?? Text( value ?? '', style: const TextStyle( fontSize: 22, fontWeight: FontWeight.w700, color: AppColors.textPrimary, ), ), const SizedBox(height: 2), Text( subtitle, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( fontSize: 11, color: AppColors.textMuted, ), ), ], ), ), ], ), ); } Widget _buildGenderCard() { final total = metrics.pacientesMasculinos + metrics.pacientesFemeninos; final mascPct = total > 0 ? ((metrics.pacientesMasculinos / total) * 100).toInt() : 81; final femPct = total > 0 ? ((metrics.pacientesFemeninos / total) * 100).toInt() : 19; return _buildMetricCard( title: 'Pacientes por Sexo', valueWidget: FittedBox( fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Row( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.baseline, textBaseline: TextBaseline.alphabetic, children: [ Text( _formatNumber(metrics.pacientesMasculinos), style: const TextStyle( fontSize: 20, fontWeight: FontWeight.w700, color: AppColors.primary, ), ), const Text( ' M', style: TextStyle( fontSize: 11, fontWeight: FontWeight.w700, color: AppColors.primary, ), ), const SizedBox(width: 8), const Text( '/', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, color: AppColors.border, ), ), const SizedBox(width: 8), Text( _formatNumber(metrics.pacientesFemeninos), style: const TextStyle( fontSize: 20, fontWeight: FontWeight.w700, color: Color(0xFFEC4899), ), ), const Text( ' F', style: TextStyle( fontSize: 11, fontWeight: FontWeight.w700, color: Color(0xFFEC4899), ), ), ], ), ), subtitle: '$mascPct% Masc · $femPct% Fem', icon: Icons.people_alt_rounded, iconColor: AppColors.secondary, bgColor: AppColors.secondary.withValues(alpha: 0.12), ); } }