From e61f1c8d668c8ad12de01612721c280140ed5b77 Mon Sep 17 00:00:00 2001 From: Kaua Marques Date: Mon, 20 Jan 2025 21:13:04 -0300 Subject: [PATCH 1/4] refatoramento da tela de paciente e nutricionista --- .../nutritionist_dashboard_screen.dart | 520 ++++++------------ 1 file changed, 170 insertions(+), 350 deletions(-) diff --git a/healthway_app/lib/screens_nutricionist/nutritionist_dashboard_screen.dart b/healthway_app/lib/screens_nutricionist/nutritionist_dashboard_screen.dart index 73f3078..53f8b54 100644 --- a/healthway_app/lib/screens_nutricionist/nutritionist_dashboard_screen.dart +++ b/healthway_app/lib/screens_nutricionist/nutritionist_dashboard_screen.dart @@ -1,6 +1,5 @@ import 'package:healthway_app/constants.dart'; import 'package:flutter/material.dart'; - class NutritionistDashboardScreen extends StatelessWidget { final Map userData; @@ -8,6 +7,7 @@ class NutritionistDashboardScreen extends StatelessWidget { @override Widget build(BuildContext context) { + return Scaffold( backgroundColor: kBackgroundColor, body: SafeArea( @@ -15,24 +15,27 @@ class NutritionistDashboardScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildHeader(context), + _buildHeader(), + _buildSectionTitle('Acesso Rápido'), _buildQuickAccess(context), + _buildSectionTitle('Próximas Consultas', showButton: true, buttonRoute: '/appointments'), _buildAppointments(context), + _buildSectionTitle('Atualizações de Pacientes', showButton: true, buttonRoute: '/patient_updates'), _buildPatientUpdates(context), ], ), ), ), - bottomNavigationBar: _buildBottomNavigationBar(context), + bottomNavigationBar: _buildBottomNavigationBar(), ); } - Widget _buildHeader(BuildContext context) { + Widget _buildHeader() { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: kPrimaryColor, - borderRadius: BorderRadius.only( + borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(30), bottomRight: Radius.circular(30), ), @@ -48,54 +51,45 @@ class NutritionistDashboardScreen extends StatelessWidget { children: [ Text( userData['nome'], - style: TextStyle( + style: const TextStyle( color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold, ), ), - SizedBox(height: 5), - Text( + const SizedBox(height: 5), + const Text( 'Bem-vindo de volta', - style: TextStyle( - color: Colors.white70, - fontSize: 16, - ), + style: TextStyle(color: Colors.white70, fontSize: 16), ), ], ), - GestureDetector( - onTap: () { - Navigator.pushNamed(context, '/nutritionistProfile'); - }, - child: CircleAvatar( - radius: 30, - backgroundColor: Colors.white, - child: Icon( - Icons.person, - size: 35, - color: kPrimaryColor, - ), - ), + CircleAvatar( + radius: 30, + backgroundImage: AssetImage('assets/images/nutricionista.jpg'), ), ], ), - SizedBox(height: 20), - Container( - padding: EdgeInsets.symmetric(horizontal: 15, vertical: 10), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _buildStatItem('Pacientes', '${userData['pacientes'].length}'), - _buildStatItem('Consultas Hoje', '8'), - _buildStatItem('Mensagens', '15'), - ], - ), - ), + const SizedBox(height: 20), + _buildStatsRow(), + ], + ), + ); + } + + Widget _buildStatsRow() { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _buildStatItem('Pacientes', '${userData['pacientes'].length}'), + _buildStatItem('Consultas Hoje', '8'), + _buildStatItem('Mensagens', '15'), ], ), ); @@ -112,14 +106,8 @@ class NutritionistDashboardScreen extends StatelessWidget { color: kPrimaryColor, ), ), - SizedBox(height: 5), - Text( - label, - style: TextStyle( - fontSize: 14, - color: Colors.grey[600], - ), - ), + const SizedBox(height: 5), + Text(label, style: TextStyle(fontSize: 14, color: Colors.grey[600])), ], ); } @@ -127,356 +115,188 @@ class NutritionistDashboardScreen extends StatelessWidget { Widget _buildQuickAccess(BuildContext context) { return Padding( padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - 'Acesso Rápido', - style: TextStyle( - color: Colors.black, - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - SizedBox(height: 15), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _buildQuickAccessItem(context, Icons.people, 'Pacientes', - '/patient_list', userData), - _buildQuickAccessItem( - context, Icons.calendar_today, 'Agenda', '/schedule', null), - // _buildQuickAccessItem( - // context, Icons.restaurant_menu, 'Planos', '/meal_plans'), - _buildQuickAccessItem(context, Icons.food_bank_outlined, - 'Alimentos', '/alimentos', null), - ], - ), + _buildQuickAccessItem(context, Icons.people, 'Pacientes', '/patient_list', userData), + _buildQuickAccessItem(context, Icons.calendar_today, 'Agenda', '/schedule', null), + _buildQuickAccessItem(context, Icons.food_bank_outlined, 'Alimentos', '/alimentos', null), ], ), ); } - Widget _buildQuickAccessItem(BuildContext context, IconData icon, - String label, String route, Object? args) { + Widget _buildQuickAccessItem( + BuildContext context, + IconData icon, + String label, + String route, + Object? args, + ) { return GestureDetector( - onTap: () { - Navigator.pushNamed(context, route, arguments: args); - }, + onTap: () => Navigator.pushNamed(context, route, arguments: args), child: Column( children: [ Container( - padding: EdgeInsets.all(15), + padding: const EdgeInsets.all(15), decoration: BoxDecoration( - color: kPrimaryColor.withValues(alpha: 0.1), + color: kPrimaryColor.withOpacity(0.1), borderRadius: BorderRadius.circular(15), ), - child: Icon( - icon, - color: kPrimaryColor, - size: 30, - ), - ), - SizedBox(height: 5), - Text( - label, - style: TextStyle( - fontSize: 14, - color: Colors.grey[600], - ), + child: Icon(icon, color: kPrimaryColor, size: 30), ), + const SizedBox(height: 5), + Text(label, style: TextStyle(fontSize: 14, color: Colors.grey[600])), ], ), ); } Widget _buildAppointments(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Próximas Consultas', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - TextButton( - onPressed: () { - Navigator.pushNamed(context, '/appointments'); - }, - child: Text( - 'Ver todas', - style: TextStyle( - color: kPrimaryColor, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - SizedBox(height: 15), - _buildAppointmentItem( - context, 'Maria Oliveira', '14:00', 'Consulta de Rotina'), - _buildAppointmentItem( - context, 'João Silva', '15:30', 'Avaliação Nutricional'), - _buildAppointmentItem( - context, 'Ana Santos', '17:00', 'Revisão de Dieta'), - ], - ), - ); - } + final appointments = [ + {'name': 'Maria Oliveira', 'time': '14:00', 'type': 'Consulta de Rotina'}, + {'name': 'João Silva', 'time': '15:30', 'type': 'Avaliação Nutricional'}, + {'name': 'Ana Santos', 'time': '17:00', 'type': 'Revisão de Dieta'}, + ]; - Widget _buildAppointmentItem( - BuildContext context, String name, String time, String type) { - return GestureDetector( - onTap: () { - Navigator.pushNamed(context, '/appointment_details', - arguments: {'name': name, 'time': time, 'type': type}); - }, - child: Container( - margin: EdgeInsets.only(bottom: 10), - padding: EdgeInsets.all(15), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15), - boxShadow: [ - BoxShadow( - color: Colors.grey.withValues(alpha: 0.1), - spreadRadius: 1, - blurRadius: 5, - offset: Offset(0, 3), - ), - ], - ), - child: Row( - children: [ - Container( - padding: EdgeInsets.all(10), - decoration: BoxDecoration( - color: kPrimaryColor.withValues(alpha: 0.1), - borderRadius: BorderRadius.circular(10), - ), - child: Icon( - Icons.calendar_today, - color: kPrimaryColor, - ), - ), - SizedBox(width: 15), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - name, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 16, - ), - ), - SizedBox(height: 5), - Text( - type, - style: TextStyle( - color: Colors.grey[600], - fontSize: 14, - ), - ), - ], - ), - ), - Text( - time, - style: TextStyle( - fontWeight: FontWeight.bold, - color: kPrimaryColor, - ), - ), - ], - ), - ), + return Column( + children: appointments + .map((appointment) => _buildAppointmentItem( + appointment['name']!, + appointment['time']!, + appointment['type']!, + )) + .toList(), ); } - Widget _buildPatientUpdates(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + Widget _buildAppointmentItem(String name, String time, String type) { + return Container( + margin: const EdgeInsets.only(bottom: 10), + padding: const EdgeInsets.all(15), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.1), + spreadRadius: 1, + blurRadius: 5, + offset: const Offset(0, 3), + ), + ], + ), + child: Row( children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Atualizações de Pacientes', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - TextButton( - onPressed: () { - Navigator.pushNamed(context, '/patient_updates'); - }, - child: Text( - 'Ver todas', - style: TextStyle( - color: kPrimaryColor, - fontWeight: FontWeight.bold, - ), + Icon(Icons.calendar_today, color: kPrimaryColor, size: 30), + const SizedBox(width: 15), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + name, + style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16), ), - ), - ], + const SizedBox(height: 5), + Text(type, style: TextStyle(color: Colors.grey[600], fontSize: 14)), + ], + ), ), - SizedBox(height: 15), - _buildPatientUpdateItem( - context, 'Carlos Mendes', 'Atingiu meta de peso', '2h atrás'), - _buildPatientUpdateItem(context, 'Fernanda Lima', - 'Novo registro de refeição', '4h atrás'), - _buildPatientUpdateItem(context, 'Ricardo Souza', - 'Solicitou alteração na dieta', '1d atrás'), + Text(time, style: TextStyle(fontWeight: FontWeight.bold, color: kPrimaryColor)), ], ), ); } - Widget _buildPatientUpdateItem( - BuildContext context, String name, String update, String time) { - return GestureDetector( - onTap: () { - Navigator.pushNamed(context, '/patient_details', - arguments: {'name': name}); - }, - child: Container( - margin: EdgeInsets.only(bottom: 10), - padding: EdgeInsets.all(15), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15), - boxShadow: [ - BoxShadow( - color: Colors.grey.withValues(alpha: 0.1), - spreadRadius: 1, - blurRadius: 5, - offset: Offset(0, 3), - ), - ], - ), - child: Row( - children: [ - CircleAvatar( - backgroundColor: kPrimaryColor.withValues(alpha: 0.1), - child: Text( - name[0], - style: TextStyle( - color: kPrimaryColor, - fontWeight: FontWeight.bold, - ), - ), - ), - SizedBox(width: 15), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - name, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 16, - ), - ), - SizedBox(height: 5), - Text( - update, - style: TextStyle( - color: Colors.grey[600], - fontSize: 14, - ), - ), - ], - ), - ), - Text( - time, - style: TextStyle( - color: Colors.grey[400], - fontSize: 12, - ), - ), - ], - ), - ), + Widget _buildPatientUpdates(BuildContext context) { + final updates = [ + {'name': 'Carlos Mendes', 'update': 'Atingiu meta de peso', 'time': '2h atrás'}, + {'name': 'Fernanda Lima', 'update': 'Novo registro de refeição', 'time': '4h atrás'}, + {'name': 'Ricardo Souza', 'update': 'Solicitou alteração na dieta', 'time': '1d atrás'}, + ]; + + return Column( + children: updates + .map((update) => _buildPatientUpdateItem( + update['name']!, + update['update']!, + update['time']!, + )) + .toList(), ); } - Widget _buildBottomNavigationBar(BuildContext context) { + Widget _buildPatientUpdateItem(String name, String update, String time) { return Container( + margin: const EdgeInsets.only(bottom: 10), + padding: const EdgeInsets.all(15), decoration: BoxDecoration( color: Colors.white, + borderRadius: BorderRadius.circular(15), boxShadow: [ BoxShadow( - color: Colors.grey.withValues(alpha: 0.3), + color: Colors.grey.withOpacity(0.1), spreadRadius: 1, blurRadius: 5, - offset: Offset(0, -3), + offset: const Offset(0, 3), ), ], ), - child: BottomNavigationBar( - backgroundColor: Colors.transparent, - elevation: 0, - selectedItemColor: kPrimaryColor, - unselectedItemColor: Colors.grey, - showSelectedLabels: true, - showUnselectedLabels: true, - type: BottomNavigationBarType.fixed, - currentIndex: 0, - onTap: (index) { - switch (index) { - case 0: - // Already on home screen - break; - case 1: - Navigator.pushNamed(context, '/patient_list', - arguments: userData); - break; - case 2: - Navigator.pushNamed(context, '/schedule'); - break; - case 3: - Navigator.pushNamed(context, '/chat'); - break; - } - }, - items: [ - BottomNavigationBarItem( - icon: Icon(Icons.home), - label: 'Início', - ), - BottomNavigationBarItem( - icon: Icon(Icons.people), - label: 'Pacientes', - ), - BottomNavigationBarItem( - icon: Icon(Icons.calendar_today), - label: 'Agenda', - ), - BottomNavigationBarItem( - icon: Icon(Icons.message), - label: 'Mensagens', + child: Row( + children: [ + Icon(Icons.notifications, color: kPrimaryColor, size: 30), + const SizedBox(width: 15), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + name, + style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16), + ), + const SizedBox(height: 5), + Text(update, style: TextStyle(color: Colors.grey[600], fontSize: 14)), + ], + ), ), + Text(time, style: TextStyle(color: Colors.grey[600], fontSize: 12)), ], ), ); } -} -extension on Color { - withValues({required double alpha}) {} + Widget _buildSectionTitle(String title, {bool showButton = false, String? buttonRoute}) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + ), + ); + } + + Widget _buildBottomNavigationBar() { + return BottomNavigationBar( + currentIndex: 0, + selectedItemColor: kPrimaryColor, + unselectedItemColor: Colors.grey, + items: const [ + BottomNavigationBarItem( + icon: Icon(Icons.dashboard), + label: 'Dashboard', + ), + BottomNavigationBarItem( + icon: Icon(Icons.people), + label: 'Pacientes', + ), + BottomNavigationBarItem( + icon: Icon(Icons.settings), + label: 'Configurações', + ), + ], + onTap: (index) { + // Implement navigation logic here + }, + ); + } } From ddfc4041d68edafaaa91bf4fff6a6705b7bd4ce0 Mon Sep 17 00:00:00 2001 From: Kaua Marques Date: Mon, 20 Jan 2025 21:44:19 -0300 Subject: [PATCH 2/4] melhorando testes --- .../nutritionist_dashboard_screen.dart | 520 ++++++++++++------ .../nutricionista_dashboard_screen_test.dart | 136 +++-- 2 files changed, 446 insertions(+), 210 deletions(-) diff --git a/healthway_app/lib/screens_nutricionist/nutritionist_dashboard_screen.dart b/healthway_app/lib/screens_nutricionist/nutritionist_dashboard_screen.dart index 53f8b54..73f3078 100644 --- a/healthway_app/lib/screens_nutricionist/nutritionist_dashboard_screen.dart +++ b/healthway_app/lib/screens_nutricionist/nutritionist_dashboard_screen.dart @@ -1,5 +1,6 @@ import 'package:healthway_app/constants.dart'; import 'package:flutter/material.dart'; + class NutritionistDashboardScreen extends StatelessWidget { final Map userData; @@ -7,7 +8,6 @@ class NutritionistDashboardScreen extends StatelessWidget { @override Widget build(BuildContext context) { - return Scaffold( backgroundColor: kBackgroundColor, body: SafeArea( @@ -15,27 +15,24 @@ class NutritionistDashboardScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildHeader(), - _buildSectionTitle('Acesso Rápido'), + _buildHeader(context), _buildQuickAccess(context), - _buildSectionTitle('Próximas Consultas', showButton: true, buttonRoute: '/appointments'), _buildAppointments(context), - _buildSectionTitle('Atualizações de Pacientes', showButton: true, buttonRoute: '/patient_updates'), _buildPatientUpdates(context), ], ), ), ), - bottomNavigationBar: _buildBottomNavigationBar(), + bottomNavigationBar: _buildBottomNavigationBar(context), ); } - Widget _buildHeader() { + Widget _buildHeader(BuildContext context) { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: kPrimaryColor, - borderRadius: const BorderRadius.only( + borderRadius: BorderRadius.only( bottomLeft: Radius.circular(30), bottomRight: Radius.circular(30), ), @@ -51,45 +48,54 @@ class NutritionistDashboardScreen extends StatelessWidget { children: [ Text( userData['nome'], - style: const TextStyle( + style: TextStyle( color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold, ), ), - const SizedBox(height: 5), - const Text( + SizedBox(height: 5), + Text( 'Bem-vindo de volta', - style: TextStyle(color: Colors.white70, fontSize: 16), + style: TextStyle( + color: Colors.white70, + fontSize: 16, + ), ), ], ), - CircleAvatar( - radius: 30, - backgroundImage: AssetImage('assets/images/nutricionista.jpg'), + GestureDetector( + onTap: () { + Navigator.pushNamed(context, '/nutritionistProfile'); + }, + child: CircleAvatar( + radius: 30, + backgroundColor: Colors.white, + child: Icon( + Icons.person, + size: 35, + color: kPrimaryColor, + ), + ), ), ], ), - const SizedBox(height: 20), - _buildStatsRow(), - ], - ), - ); - } - - Widget _buildStatsRow() { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _buildStatItem('Pacientes', '${userData['pacientes'].length}'), - _buildStatItem('Consultas Hoje', '8'), - _buildStatItem('Mensagens', '15'), + SizedBox(height: 20), + Container( + padding: EdgeInsets.symmetric(horizontal: 15, vertical: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _buildStatItem('Pacientes', '${userData['pacientes'].length}'), + _buildStatItem('Consultas Hoje', '8'), + _buildStatItem('Mensagens', '15'), + ], + ), + ), ], ), ); @@ -106,8 +112,14 @@ class NutritionistDashboardScreen extends StatelessWidget { color: kPrimaryColor, ), ), - const SizedBox(height: 5), - Text(label, style: TextStyle(fontSize: 14, color: Colors.grey[600])), + SizedBox(height: 5), + Text( + label, + style: TextStyle( + fontSize: 14, + color: Colors.grey[600], + ), + ), ], ); } @@ -115,188 +127,356 @@ class NutritionistDashboardScreen extends StatelessWidget { Widget _buildQuickAccess(BuildContext context) { return Padding( padding: const EdgeInsets.all(20), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildQuickAccessItem(context, Icons.people, 'Pacientes', '/patient_list', userData), - _buildQuickAccessItem(context, Icons.calendar_today, 'Agenda', '/schedule', null), - _buildQuickAccessItem(context, Icons.food_bank_outlined, 'Alimentos', '/alimentos', null), + Text( + 'Acesso Rápido', + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _buildQuickAccessItem(context, Icons.people, 'Pacientes', + '/patient_list', userData), + _buildQuickAccessItem( + context, Icons.calendar_today, 'Agenda', '/schedule', null), + // _buildQuickAccessItem( + // context, Icons.restaurant_menu, 'Planos', '/meal_plans'), + _buildQuickAccessItem(context, Icons.food_bank_outlined, + 'Alimentos', '/alimentos', null), + ], + ), ], ), ); } - Widget _buildQuickAccessItem( - BuildContext context, - IconData icon, - String label, - String route, - Object? args, - ) { + Widget _buildQuickAccessItem(BuildContext context, IconData icon, + String label, String route, Object? args) { return GestureDetector( - onTap: () => Navigator.pushNamed(context, route, arguments: args), + onTap: () { + Navigator.pushNamed(context, route, arguments: args); + }, child: Column( children: [ Container( - padding: const EdgeInsets.all(15), + padding: EdgeInsets.all(15), decoration: BoxDecoration( - color: kPrimaryColor.withOpacity(0.1), + color: kPrimaryColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(15), ), - child: Icon(icon, color: kPrimaryColor, size: 30), + child: Icon( + icon, + color: kPrimaryColor, + size: 30, + ), + ), + SizedBox(height: 5), + Text( + label, + style: TextStyle( + fontSize: 14, + color: Colors.grey[600], + ), ), - const SizedBox(height: 5), - Text(label, style: TextStyle(fontSize: 14, color: Colors.grey[600])), ], ), ); } Widget _buildAppointments(BuildContext context) { - final appointments = [ - {'name': 'Maria Oliveira', 'time': '14:00', 'type': 'Consulta de Rotina'}, - {'name': 'João Silva', 'time': '15:30', 'type': 'Avaliação Nutricional'}, - {'name': 'Ana Santos', 'time': '17:00', 'type': 'Revisão de Dieta'}, - ]; - - return Column( - children: appointments - .map((appointment) => _buildAppointmentItem( - appointment['name']!, - appointment['time']!, - appointment['type']!, - )) - .toList(), + return Padding( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Próximas Consultas', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + TextButton( + onPressed: () { + Navigator.pushNamed(context, '/appointments'); + }, + child: Text( + 'Ver todas', + style: TextStyle( + color: kPrimaryColor, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + SizedBox(height: 15), + _buildAppointmentItem( + context, 'Maria Oliveira', '14:00', 'Consulta de Rotina'), + _buildAppointmentItem( + context, 'João Silva', '15:30', 'Avaliação Nutricional'), + _buildAppointmentItem( + context, 'Ana Santos', '17:00', 'Revisão de Dieta'), + ], + ), ); } - Widget _buildAppointmentItem(String name, String time, String type) { - return Container( - margin: const EdgeInsets.only(bottom: 10), - padding: const EdgeInsets.all(15), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15), - boxShadow: [ - BoxShadow( - color: Colors.grey.withOpacity(0.1), - spreadRadius: 1, - blurRadius: 5, - offset: const Offset(0, 3), - ), - ], + Widget _buildAppointmentItem( + BuildContext context, String name, String time, String type) { + return GestureDetector( + onTap: () { + Navigator.pushNamed(context, '/appointment_details', + arguments: {'name': name, 'time': time, 'type': type}); + }, + child: Container( + margin: EdgeInsets.only(bottom: 10), + padding: EdgeInsets.all(15), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + boxShadow: [ + BoxShadow( + color: Colors.grey.withValues(alpha: 0.1), + spreadRadius: 1, + blurRadius: 5, + offset: Offset(0, 3), + ), + ], + ), + child: Row( + children: [ + Container( + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + color: kPrimaryColor.withValues(alpha: 0.1), + borderRadius: BorderRadius.circular(10), + ), + child: Icon( + Icons.calendar_today, + color: kPrimaryColor, + ), + ), + SizedBox(width: 15), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + name, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + SizedBox(height: 5), + Text( + type, + style: TextStyle( + color: Colors.grey[600], + fontSize: 14, + ), + ), + ], + ), + ), + Text( + time, + style: TextStyle( + fontWeight: FontWeight.bold, + color: kPrimaryColor, + ), + ), + ], + ), ), - child: Row( + ); + } + + Widget _buildPatientUpdates(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Icon(Icons.calendar_today, color: kPrimaryColor, size: 30), - const SizedBox(width: 15), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - name, - style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Atualizações de Pacientes', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, ), - const SizedBox(height: 5), - Text(type, style: TextStyle(color: Colors.grey[600], fontSize: 14)), - ], - ), + ), + TextButton( + onPressed: () { + Navigator.pushNamed(context, '/patient_updates'); + }, + child: Text( + 'Ver todas', + style: TextStyle( + color: kPrimaryColor, + fontWeight: FontWeight.bold, + ), + ), + ), + ], ), - Text(time, style: TextStyle(fontWeight: FontWeight.bold, color: kPrimaryColor)), + SizedBox(height: 15), + _buildPatientUpdateItem( + context, 'Carlos Mendes', 'Atingiu meta de peso', '2h atrás'), + _buildPatientUpdateItem(context, 'Fernanda Lima', + 'Novo registro de refeição', '4h atrás'), + _buildPatientUpdateItem(context, 'Ricardo Souza', + 'Solicitou alteração na dieta', '1d atrás'), ], ), ); } - Widget _buildPatientUpdates(BuildContext context) { - final updates = [ - {'name': 'Carlos Mendes', 'update': 'Atingiu meta de peso', 'time': '2h atrás'}, - {'name': 'Fernanda Lima', 'update': 'Novo registro de refeição', 'time': '4h atrás'}, - {'name': 'Ricardo Souza', 'update': 'Solicitou alteração na dieta', 'time': '1d atrás'}, - ]; - - return Column( - children: updates - .map((update) => _buildPatientUpdateItem( - update['name']!, - update['update']!, - update['time']!, - )) - .toList(), + Widget _buildPatientUpdateItem( + BuildContext context, String name, String update, String time) { + return GestureDetector( + onTap: () { + Navigator.pushNamed(context, '/patient_details', + arguments: {'name': name}); + }, + child: Container( + margin: EdgeInsets.only(bottom: 10), + padding: EdgeInsets.all(15), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + boxShadow: [ + BoxShadow( + color: Colors.grey.withValues(alpha: 0.1), + spreadRadius: 1, + blurRadius: 5, + offset: Offset(0, 3), + ), + ], + ), + child: Row( + children: [ + CircleAvatar( + backgroundColor: kPrimaryColor.withValues(alpha: 0.1), + child: Text( + name[0], + style: TextStyle( + color: kPrimaryColor, + fontWeight: FontWeight.bold, + ), + ), + ), + SizedBox(width: 15), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + name, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + SizedBox(height: 5), + Text( + update, + style: TextStyle( + color: Colors.grey[600], + fontSize: 14, + ), + ), + ], + ), + ), + Text( + time, + style: TextStyle( + color: Colors.grey[400], + fontSize: 12, + ), + ), + ], + ), + ), ); } - Widget _buildPatientUpdateItem(String name, String update, String time) { + Widget _buildBottomNavigationBar(BuildContext context) { return Container( - margin: const EdgeInsets.only(bottom: 10), - padding: const EdgeInsets.all(15), decoration: BoxDecoration( color: Colors.white, - borderRadius: BorderRadius.circular(15), boxShadow: [ BoxShadow( - color: Colors.grey.withOpacity(0.1), + color: Colors.grey.withValues(alpha: 0.3), spreadRadius: 1, blurRadius: 5, - offset: const Offset(0, 3), + offset: Offset(0, -3), ), ], ), - child: Row( - children: [ - Icon(Icons.notifications, color: kPrimaryColor, size: 30), - const SizedBox(width: 15), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - name, - style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16), - ), - const SizedBox(height: 5), - Text(update, style: TextStyle(color: Colors.grey[600], fontSize: 14)), - ], - ), + child: BottomNavigationBar( + backgroundColor: Colors.transparent, + elevation: 0, + selectedItemColor: kPrimaryColor, + unselectedItemColor: Colors.grey, + showSelectedLabels: true, + showUnselectedLabels: true, + type: BottomNavigationBarType.fixed, + currentIndex: 0, + onTap: (index) { + switch (index) { + case 0: + // Already on home screen + break; + case 1: + Navigator.pushNamed(context, '/patient_list', + arguments: userData); + break; + case 2: + Navigator.pushNamed(context, '/schedule'); + break; + case 3: + Navigator.pushNamed(context, '/chat'); + break; + } + }, + items: [ + BottomNavigationBarItem( + icon: Icon(Icons.home), + label: 'Início', + ), + BottomNavigationBarItem( + icon: Icon(Icons.people), + label: 'Pacientes', + ), + BottomNavigationBarItem( + icon: Icon(Icons.calendar_today), + label: 'Agenda', + ), + BottomNavigationBarItem( + icon: Icon(Icons.message), + label: 'Mensagens', ), - Text(time, style: TextStyle(color: Colors.grey[600], fontSize: 12)), ], ), ); } +} - Widget _buildSectionTitle(String title, {bool showButton = false, String? buttonRoute}) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - ), - ); - } - - Widget _buildBottomNavigationBar() { - return BottomNavigationBar( - currentIndex: 0, - selectedItemColor: kPrimaryColor, - unselectedItemColor: Colors.grey, - items: const [ - BottomNavigationBarItem( - icon: Icon(Icons.dashboard), - label: 'Dashboard', - ), - BottomNavigationBarItem( - icon: Icon(Icons.people), - label: 'Pacientes', - ), - BottomNavigationBarItem( - icon: Icon(Icons.settings), - label: 'Configurações', - ), - ], - onTap: (index) { - // Implement navigation logic here - }, - ); - } +extension on Color { + withValues({required double alpha}) {} } diff --git a/healthway_app/test/nutricionista_dashboard_screen_test.dart b/healthway_app/test/nutricionista_dashboard_screen_test.dart index 1ca5062..0f41860 100644 --- a/healthway_app/test/nutricionista_dashboard_screen_test.dart +++ b/healthway_app/test/nutricionista_dashboard_screen_test.dart @@ -1,53 +1,109 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:healthway_app/screens_nutricionist/nutritionist_dashboard_screen.dart'; +import 'package:healthway_app/screens_nutricionist/meal_plan_screen.dart'; +import 'package:healthway_app/screens_patient/patient_dashboard_screen.dart'; +import 'package:healthway_app/screens_patient/patient_profile_screen.dart'; void main() { - testWidgets('NutritionistDashboardScreen displays correctly', (WidgetTester tester) async { - // Build the NutritionistDashboardScreen widget. - await tester.pumpWidget(MaterialApp(home: NutritionistDashboardScreen(userData: {},))); - - // Verify if the background color is correct. - final scaffold = tester.widget(find.byType(Scaffold)); - expect(scaffold.backgroundColor, const Color(0xFFE6F7F8)); - - // Verify if the AppBar widget is present. - expect(find.byType(AppBar), findsOneWidget); - - // Verify if the Icon widget is present. - expect(find.byType(Icon), findsOneWidget); - - // Verify if the Padding widget is present. - expect(find.byType(Padding), findsOneWidget); - - // Verify if the Form widget is present. - expect(find.byType(Form), findsOneWidget); - - // Verify if the TextFormField widget is present. - expect(find.byType(TextFormField), findsNWidgets(2)); - - // Verify if the ElevatedButton widget is present. - expect(find.byType(ElevatedButton), findsOneWidget); - - // Verify if the CircularProgressIndicator widget is present. - expect(find.byType(CircularProgressIndicator), findsNothing); + final Map mockUserData = { + 'nome': 'John Doe', + 'email': 'ho@gmail.com', + 'dt_nascimento': '01/01/2000', + 'altura': 180, + 'peso': 75, + 'circunferencia_abdominal': 88, + 'massa_muscular': 6.5, + 'gordura_corporal': 15.5, + 'alergias': ['Amendoim', 'Leite'], + 'preferencias': ['Vegano'], + }; + + testWidgets('PatientDashboardScreen displays user data correctly', + (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp( + home: PatientDashboardScreen(userData: mockUserData), + )); + + expect(find.text('John Doe'), findsOneWidget); + expect(find.text('Vamos cuidar da sua saúde hoje!'), findsOneWidget); + expect(find.text('IMC'), findsOneWidget); + expect(find.text('Peso'), findsOneWidget); + expect(find.text('Altura'), findsOneWidget); + }); - // Add more specific tests for the widgets inside the Column as needed. + testWidgets('PatientDashboardScreen navigates to meal plan on tap', + (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp( + onGenerateRoute: (settings) { + switch (settings.name) { + case '/meal_plan': + final args = settings.arguments as Map; + return MaterialPageRoute( + builder: (context) => MealPlanScreen(patientData: args, isPatient: true), + ); + default: + return null; + } + }, + home: PatientDashboardScreen(userData: mockUserData), + )); + + await tester.tap(find.byKey(Key('dashboard_dieta'))); + await tester.pumpAndSettle(); + + expect(find.byType(PatientDashboardScreen), findsNothing); }); - testWidgets('NutritionistDashboardScreen displays CircularProgressIndicator when loading', (WidgetTester tester) async { - // Build the NutritionistDashboardScreen widget. - await tester.pumpWidget(MaterialApp(home: NutritionistDashboardScreen(userData: {},))); + testWidgets('PatientDashboardScreen displays next appointment', + (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp( + home: PatientDashboardScreen(userData: mockUserData), + )); - // Verify if the CircularProgressIndicator widget is present. - expect(find.byType(CircularProgressIndicator), findsNothing); + expect(find.text('Próxima consulta:'), findsOneWidget); + expect(find.text('Nutricionista'), findsOneWidget); + expect(find.text('Dr. João Silva'), findsOneWidget); + }); - // Tap the ElevatedButton to simulate a loading state. - await tester.tap(find.byType(ElevatedButton)); - await tester.pump(); + testWidgets('PatientProfileScreen displays user data correctly', + (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp( + home: PatientProfileScreen(userData: mockUserData), + )); + + expect(find.text('John Doe'), findsOneWidget); + expect(find.text('01/01/2000'), findsOneWidget); + expect(find.text('180 cm'), findsOneWidget); + expect(find.text('75 kg'), findsOneWidget); + expect(find.text('88 cm'), findsOneWidget); + expect(find.text('6.5 kg'), findsOneWidget); + expect(find.text('15.5%'), findsOneWidget); + expect(find.text('Amendoim'), findsOneWidget); + expect(find.text('Leite'), findsOneWidget); + expect(find.text('Vegano'), findsOneWidget); + }); - // Verify if the CircularProgressIndicator widget is present. - expect(find.byType(CircularProgressIndicator), findsOneWidget); + testWidgets('PatientProfileScreen navigates to edit profile on tap', + (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp( + onGenerateRoute: (settings) { + switch (settings.name) { + case '/edit_profile': + final args = settings.arguments as Map; + return MaterialPageRoute( + builder: (context) => PatientProfileScreen(userData: args), + ); + default: + return null; + } + }, + home: PatientProfileScreen(userData: mockUserData), + )); + + await tester.tap(find.byKey(Key('edit_profile_button'))); + await tester.pumpAndSettle(); + + expect(find.byType(PatientProfileScreen), findsNothing); }); From 4b91ba7492dbc4534b3e0eab98abb6977ac1d3b1 Mon Sep 17 00:00:00 2001 From: Kaua Marques Date: Mon, 20 Jan 2025 21:52:38 -0300 Subject: [PATCH 3/4] melhorando testes 1 --- .../nutricionista_dashboard_screen_test.dart | 100 +++--------------- 1 file changed, 16 insertions(+), 84 deletions(-) diff --git a/healthway_app/test/nutricionista_dashboard_screen_test.dart b/healthway_app/test/nutricionista_dashboard_screen_test.dart index 0f41860..63c9e73 100644 --- a/healthway_app/test/nutricionista_dashboard_screen_test.dart +++ b/healthway_app/test/nutricionista_dashboard_screen_test.dart @@ -1,110 +1,42 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:healthway_app/screens_nutricionist/meal_plan_screen.dart'; -import 'package:healthway_app/screens_patient/patient_dashboard_screen.dart'; -import 'package:healthway_app/screens_patient/patient_profile_screen.dart'; +import 'package:healthway_app/screens_nutricionist/nutritionist_dashboard_screen.dart'; void main() { - final Map mockUserData = { - 'nome': 'John Doe', - 'email': 'ho@gmail.com', - 'dt_nascimento': '01/01/2000', - 'altura': 180, - 'peso': 75, - 'circunferencia_abdominal': 88, - 'massa_muscular': 6.5, - 'gordura_corporal': 15.5, - 'alergias': ['Amendoim', 'Leite'], - 'preferencias': ['Vegano'], - }; - - testWidgets('PatientDashboardScreen displays user data correctly', + testWidgets('NutritionistDashboardScreen displays user data correctly', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( - home: PatientDashboardScreen(userData: mockUserData), + home: NutritionistDashboardScreen(userData: {},), )); - expect(find.text('John Doe'), findsOneWidget); - expect(find.text('Vamos cuidar da sua saúde hoje!'), findsOneWidget); - expect(find.text('IMC'), findsOneWidget); - expect(find.text('Peso'), findsOneWidget); - expect(find.text('Altura'), findsOneWidget); + expect(find.text('Olá, Nutricionista!'), findsOneWidget); + expect(find.text('Vamos cuidar da saúde dos seus pacientes hoje!'), + findsOneWidget); + expect(find.text('Pacientes'), findsOneWidget); + expect(find.text('Chat'), findsOneWidget); }); - testWidgets('PatientDashboardScreen navigates to meal plan on tap', + testWidgets('NutritionistDashboardScreen navigates to chat on tap', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( onGenerateRoute: (settings) { switch (settings.name) { - case '/meal_plan': - final args = settings.arguments as Map; + case '/chat_nutricionist': return MaterialPageRoute( - builder: (context) => MealPlanScreen(patientData: args, isPatient: true), + builder: (context) => Scaffold( + appBar: AppBar(title: Text('Chat')), + ), ); default: return null; } }, - home: PatientDashboardScreen(userData: mockUserData), + home: NutritionistDashboardScreen(userData: {},), )); - await tester.tap(find.byKey(Key('dashboard_dieta'))); + await tester.tap(find.byKey(Key('dashboard_chat'))); await tester.pumpAndSettle(); - expect(find.byType(PatientDashboardScreen), findsNothing); - }); - - testWidgets('PatientDashboardScreen displays next appointment', - (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp( - home: PatientDashboardScreen(userData: mockUserData), - )); - - expect(find.text('Próxima consulta:'), findsOneWidget); - expect(find.text('Nutricionista'), findsOneWidget); - expect(find.text('Dr. João Silva'), findsOneWidget); - }); - - testWidgets('PatientProfileScreen displays user data correctly', - (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp( - home: PatientProfileScreen(userData: mockUserData), - )); - - expect(find.text('John Doe'), findsOneWidget); - expect(find.text('01/01/2000'), findsOneWidget); - expect(find.text('180 cm'), findsOneWidget); - expect(find.text('75 kg'), findsOneWidget); - expect(find.text('88 cm'), findsOneWidget); - expect(find.text('6.5 kg'), findsOneWidget); - expect(find.text('15.5%'), findsOneWidget); - expect(find.text('Amendoim'), findsOneWidget); - expect(find.text('Leite'), findsOneWidget); - expect(find.text('Vegano'), findsOneWidget); + expect(find.byType(NutritionistDashboardScreen), findsNothing); }); - - testWidgets('PatientProfileScreen navigates to edit profile on tap', - (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp( - onGenerateRoute: (settings) { - switch (settings.name) { - case '/edit_profile': - final args = settings.arguments as Map; - return MaterialPageRoute( - builder: (context) => PatientProfileScreen(userData: args), - ); - default: - return null; - } - }, - home: PatientProfileScreen(userData: mockUserData), - )); - - await tester.tap(find.byKey(Key('edit_profile_button'))); - await tester.pumpAndSettle(); - - expect(find.byType(PatientProfileScreen), findsNothing); - }); - - } \ No newline at end of file From bace728a71d3655764d4941c7c5aff48c2014264 Mon Sep 17 00:00:00 2001 From: Kaua Marques Date: Mon, 20 Jan 2025 22:06:35 -0300 Subject: [PATCH 4/4] melhorando testes 2 --- .../nutricionista_dashboard_screen_test.dart | 61 +++++++++---------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/healthway_app/test/nutricionista_dashboard_screen_test.dart b/healthway_app/test/nutricionista_dashboard_screen_test.dart index 63c9e73..86b117b 100644 --- a/healthway_app/test/nutricionista_dashboard_screen_test.dart +++ b/healthway_app/test/nutricionista_dashboard_screen_test.dart @@ -3,40 +3,37 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:healthway_app/screens_nutricionist/nutritionist_dashboard_screen.dart'; void main() { - testWidgets('NutritionistDashboardScreen displays user data correctly', - (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp( - home: NutritionistDashboardScreen(userData: {},), - )); + group('NutritionistDashboardScreen', () { + testWidgets('Exibe o cabeçalho corretamente com o nome do usuário', (WidgetTester tester) async { + // Dados simulados para o teste + const String mockUserName = 'Teste Nutricionista'; - expect(find.text('Olá, Nutricionista!'), findsOneWidget); - expect(find.text('Vamos cuidar da saúde dos seus pacientes hoje!'), - findsOneWidget); - expect(find.text('Pacientes'), findsOneWidget); - expect(find.text('Chat'), findsOneWidget); - }); + // Renderiza o widget com dados de teste + await tester.pumpWidget( + MaterialApp( + home: NutritionistDashboardScreen(userData: {'name': mockUserName}), + ), + ); + + // Verifica se o texto esperado está presente + expect(find.text('Olá, Nutricionista!'), findsOneWidget); + expect(find.text(mockUserName), findsOneWidget); + }); + + testWidgets('Não exibe widgets desnecessários ou duplicados', (WidgetTester tester) async { + const String mockUserName = 'Nutricionista Exemplo'; - testWidgets('NutritionistDashboardScreen navigates to chat on tap', - (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp( - onGenerateRoute: (settings) { - switch (settings.name) { - case '/chat_nutricionist': - return MaterialPageRoute( - builder: (context) => Scaffold( - appBar: AppBar(title: Text('Chat')), - ), - ); - default: - return null; - } - }, - home: NutritionistDashboardScreen(userData: {},), - )); + await tester.pumpWidget( + MaterialApp( + home: NutritionistDashboardScreen(userData: {'name': mockUserName}), + ), + ); - await tester.tap(find.byKey(Key('dashboard_chat'))); - await tester.pumpAndSettle(); + // Verifica que apenas um widget com "Olá, Nutricionista!" existe + expect(find.text('Olá, Nutricionista!'), findsOneWidget); - expect(find.byType(NutritionistDashboardScreen), findsNothing); + // Certifica-se de que widgets com textos incorretos não existem + expect(find.text('Texto não esperado'), findsNothing); + }); }); -} \ No newline at end of file +}