vistas de mockop

This commit is contained in:
shinra32
2026-05-22 23:53:00 -06:00
parent 90236de6ab
commit c58fa571aa
10 changed files with 6677 additions and 0 deletions

290
views_v1/login_screen.dart Normal file
View File

@@ -0,0 +1,290 @@
import 'package:flutter/material.dart';
import '../theme/app_theme.dart';
import '../widgets/widgets.dart' as w;
import 'admin_screen.dart';
import 'driver_screen.dart';
import 'main_shell.dart';
enum UserRole { usuario, conductor, administrador }
class LoginScreen extends StatefulWidget {
const LoginScreen({super.key});
@override
State<LoginScreen> createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _formKey = GlobalKey<FormState>();
final _emailCtrl = TextEditingController();
final _passCtrl = TextEditingController();
UserRole _selectedRole = UserRole.usuario;
bool _obscurePass = true;
bool _loading = false;
@override
void dispose() {
_emailCtrl.dispose();
_passCtrl.dispose();
super.dispose();
}
Future<void> _login() async {
if (!_formKey.currentState!.validate()) return;
setState(() => _loading = true);
await Future.delayed(const Duration(seconds: 1)); // Simular petición
if (!mounted) return;
setState(() => _loading = false);
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (_) => _homeForRole()),
(_) => false,
);
}
Widget _homeForRole() {
switch (_selectedRole) {
case UserRole.conductor:
return const DriverShell();
case UserRole.administrador:
return const AdminShell();
case UserRole.usuario:
return const MainShell();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppTheme.background,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
iconTheme: const IconThemeData(color: AppTheme.textPrimary),
title: const Text(
'Iniciar sesión',
style: TextStyle(color: AppTheme.textPrimary, fontSize: 16),
),
),
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 8),
// ── Encabezado ─────────────────────────────────────────
Row(
children: [
Container(
width: 48,
height: 48,
decoration: BoxDecoration(
color: AppTheme.primaryLight,
borderRadius:
BorderRadius.circular(AppTheme.radiusMd),
),
child: const Icon(Icons.delete_outline_rounded,
color: AppTheme.primary, size: 26),
),
const SizedBox(width: 14),
const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('RutaVerde',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700,
color: AppTheme.textPrimary)),
Text('Bienvenido de nuevo',
style: TextStyle(
fontSize: 13,
color: AppTheme.textSecondary)),
],
),
],
),
const SizedBox(height: 32),
// ── Formulario ─────────────────────────────────────────
w.FormField(
label: 'Correo electrónico',
hint: 'tu@correo.com',
controller: _emailCtrl,
keyboardType: TextInputType.emailAddress,
),
const SizedBox(height: 16),
w.FormField(
label: 'Contraseña',
hint: '••••••••',
controller: _passCtrl,
obscureText: _obscurePass,
suffix: IconButton(
icon: Icon(
_obscurePass
? Icons.visibility_outlined
: Icons.visibility_off_outlined,
size: 18,
color: AppTheme.textSecondary,
),
onPressed: () =>
setState(() => _obscurePass = !_obscurePass),
),
),
const SizedBox(height: 16),
DropdownButtonFormField<UserRole>(
initialValue: _selectedRole,
decoration: InputDecoration(
labelText: 'Tipo de usuario',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
),
contentPadding:
const EdgeInsets.symmetric(horizontal: 14, vertical: 16),
),
items: const [
DropdownMenuItem(
value: UserRole.usuario,
child: Text('Usuario'),
),
DropdownMenuItem(
value: UserRole.conductor,
child: Text('Conductor'),
),
DropdownMenuItem(
value: UserRole.administrador,
child: Text('Administrador'),
),
],
onChanged: (value) {
if (value != null) {
setState(() => _selectedRole = value);
}
},
),
const SizedBox(height: 10),
Align(
alignment: Alignment.centerRight,
child: TextButton(
onPressed: () {},
style: TextButton.styleFrom(
foregroundColor: AppTheme.primary),
child: const Text('¿Olvidaste tu contraseña?',
style: TextStyle(fontSize: 13)),
),
),
const SizedBox(height: 24),
// ── Botón ingresar ──────────────────────────────────────
SizedBox(
width: double.infinity,
height: 52,
child: ElevatedButton(
onPressed: _loading ? null : _login,
child: _loading
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2, color: Colors.white),
)
: const Text('Ingresar'),
),
),
const SizedBox(height: 28),
// ── Divisor ─────────────────────────────────────────────
Row(
children: [
const Expanded(child: Divider(color: AppTheme.border)),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Text('o',
style: TextStyle(
fontSize: 13, color: AppTheme.textSecondary)),
),
const Expanded(child: Divider(color: AppTheme.border)),
],
),
const SizedBox(height: 20),
// ── Continuar con Google ────────────────────────────────
_SocialButton(
icon: Icons.g_mobiledata_rounded,
label: 'Continuar con Google',
onTap: () {},
),
const SizedBox(height: 36),
// ── Crear cuenta ────────────────────────────────────────
Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Text('¿No tienes cuenta? ',
style: TextStyle(
fontSize: 13, color: AppTheme.textSecondary)),
GestureDetector(
onTap: () => Navigator.pop(context),
child: const Text('Regístrate',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w600,
color: AppTheme.primary)),
),
],
),
),
],
),
),
),
),
);
}
}
class _SocialButton extends StatelessWidget {
final IconData icon;
final String label;
final VoidCallback onTap;
const _SocialButton(
{required this.icon, required this.label, required this.onTap});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(vertical: 13),
decoration: BoxDecoration(
color: AppTheme.surface,
borderRadius: BorderRadius.circular(AppTheme.radiusMd),
border: Border.all(color: AppTheme.border),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(icon, size: 22, color: AppTheme.textPrimary),
const SizedBox(width: 10),
Text(label,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: AppTheme.textPrimary)),
],
),
),
);
}
}