import 'package:flutter/material.dart'; import 'domicilios.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @override State createState() => _LoginScreenState(); } class _LoginScreenState extends State { final _formKey = GlobalKey(); final TextEditingController emailController = TextEditingController(); final TextEditingController passwordController = TextEditingController(); bool ocultarPassword = true; void iniciarSesion() { if (_formKey.currentState!.validate()) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Inicio de sesión exitoso'), backgroundColor: Colors.green, ), ); Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => const GestionDomiciliosScreen(), ), ); } } @override Widget build(BuildContext context) { return Scaffold( body: Stack( children: [ // ── Fondo azul cielo ── Container( width: double.infinity, height: double.infinity, color: const Color(0xFF5BB8E8), ), // ── Barras de colores en la parte superior ── Column( children: [ Container(height: 10, color: const Color(0xFFE8534A)), Container(height: 8, color: const Color(0xFFF5A623)), Container(height: 8, color: const Color(0xFFFFD700)), Container(height: 8, color: const Color(0xFF4CAF50)), ], ), // ── Forma orgánica azul oscuro detrás del contenido ── Positioned( top: 60, left: -40, right: -40, child: Container( height: 420, decoration: BoxDecoration( color: const Color(0xFF4AA8D8).withValues(alpha:0.6), borderRadius: BorderRadius.circular(200), ), ), ), // ── Montañas verdes atrás ── Positioned( bottom: 80, right: -10, child: CustomPaint( size: const Size(160, 130), painter: _MountainPainter(color: const Color(0xFF2E7D32)), ), ), Positioned( bottom: 80, right: 60, child: CustomPaint( size: const Size(120, 100), painter: _MountainPainter(color: const Color(0xFF388E3C)), ), ), // ── Suelo verde ── Positioned( bottom: 0, left: 0, right: 0, child: Container( height: 90, color: const Color(0xFF4CAF50), ), ), // ── Carretera ── Positioned( bottom: 30, left: 0, right: 0, child: Container( height: 18, color: const Color(0xFF424242), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: List.generate( 12, (_) => Container( width: 20, height: 3, color: Colors.white, ), ), ), ), ), // ── Casas pequeñas ── Positioned( bottom: 45, left: 20, child: _buildHouse(const Color(0xFF90A4AE), 40), ), Positioned( bottom: 45, left: 80, child: _buildHouse(const Color(0xFF795548), 35), ), Positioned( bottom: 45, right: 20, child: _buildHouse(const Color(0xFFFFCC80), 45), ), // ── Camiones de basura ── Positioned( bottom: 33, left: 110, child: _buildTruck(const Color(0xFFE53935)), ), Positioned( bottom: 33, right: 80, child: _buildTruck(const Color(0xFFE53935)), ), // ── Basura (montón gris izquierda) ── Positioned( bottom: 90, left: 10, child: CustomPaint( size: const Size(60, 35), painter: _TrashPilePainter(), ), ), // ── Contenido principal ── SafeArea( child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 30), child: Form( key: _formKey, child: Column( children: [ const SizedBox(height: 50), // Título ECOUBICEL const Text( 'ECOUBICEL.', style: TextStyle( fontSize: 32, fontWeight: FontWeight.w900, color: Colors.black87, letterSpacing: 2, ), ), const SizedBox(height: 16), // Botes de basura Row( mainAxisAlignment: MainAxisAlignment.center, children: [ _buildTrashCan(const Color(0xFF2E7D32), Icons.recycling), const SizedBox(width: 8), _buildTrashCan(const Color(0xFFF9A825), Icons.recycling), const SizedBox(width: 8), _buildTrashCan(const Color(0xFFC62828), Icons.recycling), const SizedBox(width: 12), // Ícono de reciclaje Icon( Icons.recycling, size: 48, color: Colors.green.shade600, ), ], ), const SizedBox(height: 28), // Campo correo — barra verde _buildColorField( controller: emailController, hint: 'Correo Electrónico', icon: Icons.email, color: const Color(0xFF4CAF50), obscure: false, validator: (value) { if (value == null || value.isEmpty) return 'Ingresa tu correo'; if (!value.contains('@')) return 'Correo inválido'; return null; }, ), const SizedBox(height: 12), // Campo contraseña — barra azul _buildColorField( controller: passwordController, hint: 'Contraseña', icon: Icons.lock, color: const Color(0xFF1E88E5), obscure: ocultarPassword, suffixIcon: IconButton( icon: Icon( ocultarPassword ? Icons.visibility_off : Icons.visibility, color: Colors.white70, ), onPressed: () => setState(() => ocultarPassword = !ocultarPassword), ), validator: (value) { if (value == null || value.isEmpty) return 'Ingresa tu contraseña'; if (value.length < 6) return 'Mínimo 6 caracteres'; return null; }, ), const SizedBox(height: 12), // Botón iniciar sesión — barra naranja SizedBox( width: double.infinity, height: 48, child: ElevatedButton( onPressed: iniciarSesion, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFFE65100), foregroundColor: Colors.white, shape: const StadiumBorder(), elevation: 3, ), child: const Text( 'Iniciar Sesión', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), ), ), const SizedBox(height: 12), // Botón registrarse — barra gris SizedBox( width: double.infinity, height: 48, child: OutlinedButton( onPressed: () {}, style: OutlinedButton.styleFrom( foregroundColor: Colors.white, side: const BorderSide(color: Colors.white54, width: 2), backgroundColor: Colors.white24, shape: const StadiumBorder(), ), child: const Text( '¿No tienes cuenta? Registrarse', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, ), ), ), ), const SizedBox(height: 120), ], ), ), ), ), ), ], ), ); } // Widget bote de basura Widget _buildTrashCan(Color color, IconData icon) { return Container( width: 52, height: 64, decoration: BoxDecoration( color: color, borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow(color: Colors.black26, blurRadius: 4, offset: const Offset(2, 2)), ], ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( height: 8, margin: const EdgeInsets.symmetric(horizontal: 4), decoration: BoxDecoration( color: color.withValues(alpha:0.7), borderRadius: BorderRadius.circular(4), ), ), const SizedBox(height: 4), Icon(icon, color: Colors.white, size: 28), Container( height: 6, margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), decoration: BoxDecoration( color: Colors.black26, borderRadius: BorderRadius.circular(3), ), ), ], ), ); } // Campo de texto con fondo de color tipo barra Widget _buildColorField({ required TextEditingController controller, required String hint, required IconData icon, required Color color, required bool obscure, Widget? suffixIcon, required String? Function(String?) validator, }) { return TextFormField( controller: controller, obscureText: obscure, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w600), decoration: InputDecoration( hintText: hint, hintStyle: const TextStyle(color: Colors.white70), prefixIcon: Icon(icon, color: Colors.white), suffixIcon: suffixIcon, filled: true, fillColor: color, border: OutlineInputBorder( borderRadius: BorderRadius.circular(30), borderSide: BorderSide.none, ), errorStyle: const TextStyle(color: Colors.yellow), contentPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 14), ), validator: validator, ); } // Casa pequeña Widget _buildHouse(Color color, double size) { return CustomPaint( size: Size(size, size * 0.9), painter: _HousePainter(color: color), ); } // Camión pequeño Widget _buildTruck(Color color) { return Container( width: 36, height: 18, decoration: BoxDecoration( color: color, borderRadius: BorderRadius.circular(3), ), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Container( width: 12, height: 14, margin: const EdgeInsets.only(right: 2, top: 0), decoration: BoxDecoration( color: color.withValues(alpha:0.7), borderRadius: const BorderRadius.only( topRight: Radius.circular(3), topLeft: Radius.circular(2), ), ), ), ], ), ); } } // Pintor de montañas class _MountainPainter extends CustomPainter { final Color color; _MountainPainter({required this.color}); @override void paint(Canvas canvas, Size size) { final paint = Paint()..color = color; final path = Path() ..moveTo(0, size.height) ..lineTo(size.width / 2, 0) ..lineTo(size.width, size.height) ..close(); canvas.drawPath(path, paint); } @override bool shouldRepaint(_) => false; } // Pintor de casa class _HousePainter extends CustomPainter { final Color color; _HousePainter({required this.color}); @override void paint(Canvas canvas, Size size) { final paint = Paint()..color = color; // Cuerpo canvas.drawRect( Rect.fromLTWH(0, size.height * 0.4, size.width, size.height * 0.6), paint, ); // Techo final roof = Paint()..color = const Color(0xFFB71C1C); final path = Path() ..moveTo(0, size.height * 0.4) ..lineTo(size.width / 2, 0) ..lineTo(size.width, size.height * 0.4) ..close(); canvas.drawPath(path, roof); // Ventana canvas.drawRect( Rect.fromLTWH(size.width * 0.25, size.height * 0.55, size.width * 0.2, size.height * 0.2), Paint()..color = const Color(0xFFB3E5FC), ); // Puerta canvas.drawRect( Rect.fromLTWH(size.width * 0.55, size.height * 0.65, size.width * 0.2, size.height * 0.35), Paint()..color = const Color(0xFF5D4037), ); } @override bool shouldRepaint(_) => false; } // Pintor de montón de basura class _TrashPilePainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final paint = Paint()..color = const Color(0xFF757575); canvas.drawOval( Rect.fromLTWH(0, size.height * 0.3, size.width, size.height * 0.7), paint, ); canvas.drawOval( Rect.fromLTWH(size.width * 0.1, 0, size.width * 0.5, size.height * 0.6), Paint()..color = const Color(0xFF616161), ); canvas.drawOval( Rect.fromLTWH(size.width * 0.5, size.height * 0.1, size.width * 0.4, size.height * 0.5), Paint()..color = const Color(0xFF9E9E9E), ); } @override bool shouldRepaint(_) => false; }