// lib/features/routes/presentation/widgets/route_assignment_widget.dart // Este widget demuestra el motor espacial Haversine a los jueces. import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../providers/routes_provider.dart'; import '../../domain/entities/haversine.dart'; class RouteAssignmentWidget extends ConsumerWidget { final double userLat; final double userLng; const RouteAssignmentWidget({ super.key, required this.userLat, required this.userLng, }); @override Widget build(BuildContext context, WidgetRef ref) { final assignmentAsync = ref.watch( routeAssignmentProvider((lat: userLat, lng: userLng)), ); return assignmentAsync.when( loading: () => const _AssignmentSkeleton(), error: (e, _) => Text('Error: $e'), data: (result) => _AssignmentResult( result: result, userLat: userLat, userLng: userLng, ), ); } } class _AssignmentResult extends StatelessWidget { final RouteAssignmentResult result; final double userLat; final double userLng; const _AssignmentResult({ required this.result, required this.userLat, required this.userLng, }); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: const Color(0xFF1B5E20).withOpacity(0.05), borderRadius: BorderRadius.circular(12), border: Border.all( color: const Color(0xFF1B5E20).withOpacity(0.2), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Título con ícono de motor espacial Row( children: [ const Icon( Icons.calculate, color: Color(0xFF1B5E20), size: 20, ), const SizedBox(width: 8), const Text( 'Asignación automática', style: TextStyle( fontWeight: FontWeight.w700, fontSize: 14, color: Color(0xFF1B5E20), ), ), const Spacer(), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), decoration: BoxDecoration( color: Colors.blue.withOpacity(0.1), borderRadius: BorderRadius.circular(10), ), child: const Text( 'Haversine', style: TextStyle( fontSize: 10, color: Colors.blue, fontWeight: FontWeight.w600, ), ), ), ], ), const SizedBox(height: 12), // Ruta asignada Text( result.routeId, style: const TextStyle( fontSize: 20, fontWeight: FontWeight.w800, color: Color(0xFF1B5E20), ), ), Text( result.routeName, style: TextStyle( fontSize: 13, color: Colors.grey[700], ), ), const SizedBox(height: 12), // Distancia calculada Row( children: [ const Icon(Icons.straighten, size: 16, color: Colors.grey), const SizedBox(width: 6), Text( 'Distancia al centroide: ${result.distanceText}', style: TextStyle(fontSize: 12, color: Colors.grey[600]), ), ], ), const SizedBox(height: 4), // Coordenadas del usuario (para debug/demo) Row( children: [ const Icon(Icons.location_on, size: 16, color: Colors.grey), const SizedBox(width: 6), Text( 'Tu ubicación: ${userLat.toStringAsFixed(4)}, ${userLng.toStringAsFixed(4)}', style: TextStyle(fontSize: 12, color: Colors.grey[600]), ), ], ), const SizedBox(height: 10), // Nota de privacidad Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), decoration: BoxDecoration( color: Colors.green.withOpacity(0.08), borderRadius: BorderRadius.circular(8), ), child: Row( children: [ const Icon( Icons.shield_outlined, size: 14, color: Color(0xFF2E7D32), ), const SizedBox(width: 6), Expanded( child: Text( 'Motor espacial propio — sin llamadas externas', style: TextStyle( fontSize: 11, color: Colors.green[800], ), ), ), ], ), ), ], ), ); } } class _AssignmentSkeleton extends StatelessWidget { const _AssignmentSkeleton(); @override Widget build(BuildContext context) { return Container( height: 120, decoration: BoxDecoration( color: Colors.grey[100], borderRadius: BorderRadius.circular(12), ), child: const Center( child: CircularProgressIndicator(), ), ); } }