From 1e962af6e84431279a7ef76b59e1ad5febc79f34 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Thu, 25 Jun 2026 16:06:35 -0500 Subject: [PATCH] feat: redesign professional pending and denied screens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - professional_denied_screen: full UI with icon, bullet list of next steps, re-register button and logout option (was just a Text widget) - professional_pending_screen: replace static GIF screen with step-by-step progress indicator (submitted → in review → approved), notification tip, logout button Co-Authored-By: Claude Sonnet 4.6 --- .../professional_denied_screen.dart | 112 +++++++++- .../professional_pending_screen.dart | 208 +++++++++++++----- 2 files changed, 261 insertions(+), 59 deletions(-) diff --git a/lib/screens/professional/professional_denied_screen.dart b/lib/screens/professional/professional_denied_screen.dart index 8968594..a831bae 100644 --- a/lib/screens/professional/professional_denied_screen.dart +++ b/lib/screens/professional/professional_denied_screen.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:prosappco/blocs/authentication_bloc/authentication_bloc.dart'; class ProfessionalDeniedScreen extends StatelessWidget { const ProfessionalDeniedScreen({super.key}); @@ -6,8 +8,114 @@ class ProfessionalDeniedScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Perfil profesional')), - body: const Center(child: Text('Cuenta denegada')), + body: SafeArea( + child: SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 40), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 88, + height: 88, + decoration: BoxDecoration( + color: const Color(0xFFFFEBEE), + shape: BoxShape.circle, + ), + child: const Icon(Icons.cancel_outlined, color: Color(0xFFE53935), size: 48), + ), + const SizedBox(height: 24), + const Text( + 'Solicitud rechazada', + style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: Color(0xFF1A1A2E)), + textAlign: TextAlign.center, + ), + const SizedBox(height: 12), + const Text( + 'Tu solicitud para convertirte en profesional no fue aprobada. Esto puede deberse a información incompleta o documentación no válida.', + textAlign: TextAlign.center, + style: TextStyle(fontSize: 14, color: Colors.grey, height: 1.5), + ), + const SizedBox(height: 32), + Container( + width: double.infinity, + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: const Color(0xFFFFF3E0), + borderRadius: BorderRadius.circular(16), + border: Border.all(color: const Color(0xFFFFCC02).withOpacity(0.4)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + Row( + children: [ + Icon(Icons.info_outline, color: Color(0xFFF57C00), size: 20), + SizedBox(width: 8), + Text('¿Qué puedo hacer?', style: TextStyle(fontWeight: FontWeight.w600, color: Color(0xFFF57C00))), + ], + ), + SizedBox(height: 12), + _BulletPoint(text: 'Verifica que todos tus datos sean correctos'), + _BulletPoint(text: 'Asegúrate de haber adjuntado los documentos requeridos'), + _BulletPoint(text: 'Vuelve a registrarte como profesional con la información actualizada'), + _BulletPoint(text: 'Contacta a soporte si crees que fue un error'), + ], + ), + ), + const SizedBox(height: 32), + SizedBox( + width: double.infinity, + child: ElevatedButton.icon( + onPressed: () => Navigator.of(context).pop(), + icon: const Icon(Icons.refresh), + label: const Text('Volver a registrarme'), + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF42A4EF), + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric(vertical: 16), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + elevation: 0, + ), + ), + ), + const SizedBox(height: 12), + SizedBox( + width: double.infinity, + child: OutlinedButton.icon( + onPressed: () => context.read().add(AuthenticationLogoutRequested()), + icon: const Icon(Icons.logout), + label: const Text('Cerrar sesión'), + style: OutlinedButton.styleFrom( + foregroundColor: Colors.grey, + padding: const EdgeInsets.symmetric(vertical: 14), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + side: const BorderSide(color: Colors.grey), + ), + ), + ), + ], + ), + ), + ), + ); + } +} + +class _BulletPoint extends StatelessWidget { + final String text; + const _BulletPoint({required this.text}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(bottom: 6), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('• ', style: TextStyle(color: Color(0xFFF57C00), fontWeight: FontWeight.bold)), + Expanded(child: Text(text, style: const TextStyle(fontSize: 13, color: Color(0xFF5D4037)))), + ], + ), ); } } diff --git a/lib/screens/professional/professional_pending_screen.dart b/lib/screens/professional/professional_pending_screen.dart index c513926..1d3e309 100644 --- a/lib/screens/professional/professional_pending_screen.dart +++ b/lib/screens/professional/professional_pending_screen.dart @@ -1,77 +1,100 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:prosappco/blocs/authentication_bloc/authentication_bloc.dart'; class ProfessionalPendingScreen extends StatelessWidget { - const ProfessionalPendingScreen({Key? key}) : super(key: key); + const ProfessionalPendingScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Perfil profesional')), - body: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.only(top: 40), + body: SafeArea( + child: SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 40), child: Column( - mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.access_time, - color: Color(0xFF2BA4EC), - ), - SizedBox(width: 8), - Text( - 'Información en revisión', - style: TextStyle( - color: Color(0xFF2BA4EC), - fontSize: 17, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - Image( - image: const AssetImage('images/checklist.gif'), - width: MediaQuery.of(context).size.width * 0.7, - ), Container( - margin: const EdgeInsets.only(left: 40, right: 40, top: 20), + width: 88, + height: 88, decoration: BoxDecoration( - color: const Color(0xFFD6F4FF), - borderRadius: BorderRadius.circular(30), - boxShadow: [ - BoxShadow( - color: Colors.grey.withOpacity(0.5), - spreadRadius: 2, - blurRadius: 5, - offset: const Offset(0, 3), - ), - ], + color: const Color(0xFFE3F2FD), + shape: BoxShape.circle, ), - padding: - const EdgeInsets.symmetric(vertical: 15, horizontal: 25), - child: Column( - children: [ - SizedBox( - width: MediaQuery.of(context).size.width * 0.8, - child: const Column( - children: [ - Text( - 'Gracias por proporcionar tu información. Actualmente, estamos revisando tus datos y una vez aprobados, podrás acceder al perfil profesional sin problemas. Te notificaremos tan pronto como tu cuenta esté lista.', - style: TextStyle(fontSize: 14), - ), - SizedBox(height: 10), - Text( - '¡Gracias por tu paciencia!', - style: TextStyle(fontSize: 14), - ), - ], + child: const Icon(Icons.hourglass_top_rounded, color: Color(0xFF42A4EF), size: 48), + ), + const SizedBox(height: 24), + const Text( + 'Solicitud en revisión', + style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: Color(0xFF1A1A2E)), + textAlign: TextAlign.center, + ), + const SizedBox(height: 12), + const Text( + 'Recibimos tu información y la estamos revisando. Te notificaremos en cuanto tu perfil profesional sea aprobado.', + textAlign: TextAlign.center, + style: TextStyle(fontSize: 14, color: Colors.grey, height: 1.5), + ), + const SizedBox(height: 32), + _StepCard( + step: '1', + icon: Icons.upload_file_outlined, + title: 'Información enviada', + subtitle: 'Recibimos tu solicitud y documentos', + done: true, + ), + const SizedBox(height: 12), + _StepCard( + step: '2', + icon: Icons.manage_search_outlined, + title: 'En revisión', + subtitle: 'Nuestro equipo está verificando tus datos', + active: true, + ), + const SizedBox(height: 12), + _StepCard( + step: '3', + icon: Icons.verified_outlined, + title: 'Aprobación', + subtitle: 'Recibirás una notificación cuando esté listo', + ), + const SizedBox(height: 36), + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: const Color(0xFFF5F8FF), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: const Color(0xFFBBDEFB)), + ), + child: Row( + children: const [ + Icon(Icons.notifications_active_outlined, color: Color(0xFF42A4EF)), + SizedBox(width: 12), + Expanded( + child: Text( + 'Asegúrate de tener las notificaciones activas para recibir el aviso de aprobación.', + style: TextStyle(fontSize: 13, color: Color(0xFF1565C0)), ), ), ], ), ), + const SizedBox(height: 32), + SizedBox( + width: double.infinity, + child: OutlinedButton.icon( + onPressed: () => context.read().add(AuthenticationLogoutRequested()), + icon: const Icon(Icons.logout), + label: const Text('Cerrar sesión'), + style: OutlinedButton.styleFrom( + foregroundColor: Colors.grey, + padding: const EdgeInsets.symmetric(vertical: 14), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + side: const BorderSide(color: Colors.grey), + ), + ), + ), ], ), ), @@ -79,3 +102,74 @@ class ProfessionalPendingScreen extends StatelessWidget { ); } } + +class _StepCard extends StatelessWidget { + final String step; + final IconData icon; + final String title; + final String subtitle; + final bool done; + final bool active; + + const _StepCard({ + required this.step, + required this.icon, + required this.title, + required this.subtitle, + this.done = false, + this.active = false, + }); + + @override + Widget build(BuildContext context) { + final Color bg = done + ? const Color(0xFFE8F5E9) + : active + ? const Color(0xFFE3F2FD) + : const Color(0xFFF5F5F5); + final Color iconColor = done + ? const Color(0xFF43A047) + : active + ? const Color(0xFF42A4EF) + : Colors.grey; + final Color borderColor = done + ? const Color(0xFFA5D6A7) + : active + ? const Color(0xFF90CAF9) + : const Color(0xFFE0E0E0); + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), + decoration: BoxDecoration( + color: bg, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: borderColor), + ), + child: Row( + children: [ + Container( + width: 40, + height: 40, + decoration: BoxDecoration( + color: done ? const Color(0xFF43A047) : active ? const Color(0xFF42A4EF) : Colors.grey.shade300, + shape: BoxShape.circle, + ), + child: done + ? const Icon(Icons.check, color: Colors.white, size: 20) + : Icon(icon, color: active ? Colors.white : Colors.grey, size: 20), + ), + const SizedBox(width: 14), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(title, style: TextStyle(fontWeight: FontWeight.w600, color: iconColor)), + Text(subtitle, style: const TextStyle(fontSize: 12, color: Colors.grey)), + ], + ), + ), + ], + ), + ); + } +}