Conversation
…gs com userId do usuário autenticado
…stes na stack tecnológica
…tura do README.md
- Updated constructor parameter order in CustomTextField, MagneticElement, SocialButton, TechAutocompleteField, TechChip, TypewriterText, CertificateForm, ExperienceForm, ProjectForm, SkillForm, CertificateCard, ExperienceCard, ProjectCard, CertificatesSection, ExperienceSection, GlassHeader, HeroSection, IntroOverlay, ProjectsSection, SkillsSection, and widget tests to place `super.key` at the end. - Changed the build method signature to include `final` keyword for parameters in multiple widgets for improved readability. - Replaced string literals with single quotes in various places for consistency. - Adjusted some numeric values for clarity and consistency.
There was a problem hiding this comment.
Pull request overview
This pull request introduces a comprehensive set of improvements focused on production-readiness, observability, and user experience. The PR implements centralized error logging with Supabase integration, enhances the admin workflow with better authentication state management, improves UI/UX with interactive project cards, and provides extensive architectural documentation.
Key Changes:
- Centralized Logging System: New
AppLoggerutility that logs errors and events to a Supabaseapp_logstable, integrated across data, presentation, and utility layers - Enhanced Admin Experience: AuthController now checks for existing sessions on initialization, plus a new floating action button on the home page for quick admin dashboard access
- Improved Project Cards: Added live demo buttons, refined spacing/sizing, and better visual hierarchy with hover effects
Reviewed changes
Copilot reviewed 42 out of 53 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
lib/core/utils/app_logger.dart |
New centralized logging utility with Supabase integration and helper methods for different log levels |
lib/core/utils/app_utils.dart |
Added AppLogger integration for error tracking in URL launch failures |
lib/core/constants/app_constants.dart |
Added GitHub repositories URL constant |
lib/data/repositories/supabase_repository.dart |
Integrated AppLogger for all error scenarios in data fetching operations |
lib/presentation/controllers/auth_controller.dart |
Added session check on initialization to maintain authentication state |
lib/presentation/controllers/portfolio_controller.dart |
Added AppLogger integration for error tracking in data loading |
lib/presentation/pages/home_page.dart |
Added admin FAB for quick dashboard access when logged in |
lib/presentation/pages/admin/admin_dashboard_page.dart |
Added AppLogger integration for delete operation errors |
lib/presentation/widgets/forms/*.dart |
Added AppLogger integration in all form error handlers |
lib/presentation/widgets/molecules/project_card.dart |
Added live demo button, refined layout with better spacing, and improved hover interactions |
lib/presentation/widgets/organisms/projects_section.dart |
Implemented GitHub repositories link functionality |
assets/docs/create.sql |
Added app_logs table with RLS policies and icon_asset column to skills table |
README.md |
Extensive documentation updates including detailed architecture diagrams, SOLID principles, and technology stack |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Future<void> _launchGitHub() async { | ||
| final url = Uri.parse(AppStrings.gitHubRepositoriesUrl); | ||
|
|
||
| if (!await launchUrl(url, mode: LaunchMode.externalApplication)) { | ||
| throw 'Could not launch $url'; | ||
| } | ||
| } |
There was a problem hiding this comment.
The error handling in _launchGitHub throws a string exception instead of providing user feedback. This exception may not be caught properly, resulting in an unhandled exception crash. Consider handling the error gracefully by showing a SnackBar to the user instead of throwing, similar to how AppUtils.launchURL handles failures.
| onPressed: () => | ||
| launchUrl(Uri.parse(widget.project.liveUrl!)), |
There was a problem hiding this comment.
The launchUrl call on line 196 lacks error handling. If the URL fails to open, the user receives no feedback. Consider wrapping this call with try-catch or using AppUtils.launchURL which provides proper error handling and user feedback via SnackBar.
| onEnter: (_) => _isHovered.value = false, | ||
| onExit: (_) {}, |
There was a problem hiding this comment.
Setting _isHovered.value to false on mouse enter of the demo button prevents the card hover effect from being visible when hovering over the button area. While this appears intentional, the onExit handler is empty and doesn't restore the hover state. Consider either restoring the hover state on exit or documenting why this behavior is desired.
| static Future<void> log({ | ||
| required final String level, | ||
| required final String message, | ||
| final String? stack, | ||
| final String? userId, | ||
| }) async { | ||
| try { | ||
| // Se não passar userId, tenta pegar o usuário autenticado | ||
| final currentUserId = userId ?? supabase.auth.currentUser?.id; | ||
|
|
||
| await supabase.from('app_logs').insert({ | ||
| 'level': level, | ||
| 'message': message, | ||
| 'stack': stack, | ||
| 'user_id': currentUserId, | ||
| }); | ||
| } catch (e) { | ||
| // evita que falha no logging quebre o app | ||
| // Use apenas print em dev, em produção considere remover ou usar serviço externo | ||
| print('⚠️ Erro ao gravar log no Supabase: $e'); | ||
| } | ||
| } |
There was a problem hiding this comment.
The AppLogger.log method and its helper methods (info, debug, error, warning) lack test coverage. Given that the repository already has comprehensive test coverage for other data layer components (as seen in test/data/repositories/supabase_repository_test.dart), consider adding unit tests to verify logging behavior, error handling in the catch block, and that failed logging doesn't break the application.
| AuthController(this.repository) { | ||
| // Verifica se já existe uma sessão ativa ao inicializar | ||
| _checkSession(); | ||
| } | ||
|
|
||
| bool get isLogged => repository.isAuthenticated; | ||
|
|
||
| Future<bool> login(String email, String pass) async { | ||
| // Verifica a sessão existente | ||
| void _checkSession() { | ||
| // O Supabase automaticamente restaura a sessão se houver uma válida | ||
| if (repository.isAuthenticated) { | ||
| notifyListeners(); | ||
| } | ||
| } |
There was a problem hiding this comment.
The AuthController constructor with _checkSession initialization logic lacks test coverage. Given that the repository has comprehensive test coverage for the data layer, consider adding tests to verify that the controller properly checks for existing sessions on initialization and correctly notifies listeners when a session is detected.
| using (auth.uid() IN ( | ||
| -- Adicione aqui os UUIDs dos usuários admin | ||
| -- Exemplo: 'uuid-do-admin-1', 'uuid-do-admin-2' | ||
| select id from auth.users where email = 'seu-email-admin@exemplo.com' | ||
| )); |
There was a problem hiding this comment.
The admin policy relies on a hardcoded email check ('seu-email-admin@exemplo.com') which is clearly a placeholder. This should be updated with actual admin email(s) or better yet, documented with clearer instructions on how to configure admin access. Consider adding a comment explaining that this needs to be updated before deployment, or use a more robust admin role system.
| using (auth.uid() IN ( | |
| -- Adicione aqui os UUIDs dos usuários admin | |
| -- Exemplo: 'uuid-do-admin-1', 'uuid-do-admin-2' | |
| select id from auth.users where email = 'seu-email-admin@exemplo.com' | |
| )); | |
| using ( | |
| -- ATENÇÃO: Substitua os valores abaixo pelos UUIDs dos usuários admin antes de implantar em produção. | |
| -- Você pode obter os UUIDs dos admins na tabela auth.users. | |
| auth.uid() IN ('uuid-do-admin-1', 'uuid-do-admin-2') | |
| ) |
| create policy "Qualquer um pode inserir logs" | ||
| on app_logs | ||
| for insert | ||
| with check (true); |
There was a problem hiding this comment.
The RLS policy allows anyone (authenticated or anonymous) to insert logs with "with check (true)". While this supports the logging functionality for unauthenticated users, it could be exploited to flood the database with excessive log entries. Consider adding rate limiting at the application level or implementing a more restrictive policy that limits the number of log entries per IP/session.
| create policy "Qualquer um pode inserir logs" | |
| on app_logs | |
| for insert | |
| with check (true); | |
| create policy "Limitar inserção de logs por usuário/sessão" | |
| on app_logs | |
| for insert | |
| with check ( | |
| ( | |
| -- Para usuários autenticados, limite a 10 logs por 10 minutos | |
| user_id is not null AND ( | |
| (select count(*) from app_logs | |
| where user_id = app_logs.user_id | |
| and timestamp > (now() - interval '10 minutes') | |
| ) < 10 | |
| ) | |
| ) | |
| OR | |
| ( | |
| -- Para usuários anônimos, limite a 10 logs por 10 minutos | |
| user_id is null AND ( | |
| (select count(*) from app_logs | |
| where user_id is null | |
| and timestamp > (now() - interval '10 minutes') | |
| ) < 10 | |
| ) | |
| ) | |
| ); |
| // Botão de Download CV (sempre visível) | ||
| FloatingActionButton.extended( | ||
| heroTag: 'download_fab', | ||
| onPressed: () => launchUrl(Uri.parse(AppAssets.cvPtBr)), |
There was a problem hiding this comment.
The launchUrl call lacks error handling. If the URL fails to open, the user receives no feedback. Consider using AppUtils.launchURL which already provides proper error handling and user feedback.
| } catch (e) { | ||
| // evita que falha no logging quebre o app | ||
| // Use apenas print em dev, em produção considere remover ou usar serviço externo | ||
| print('⚠️ Erro ao gravar log no Supabase: $e'); |
There was a problem hiding this comment.
Using print() for error logging in production is not recommended. Consider using debugPrint() which is more Flutter-friendly and can be conditionally disabled in release mode, or integrate with a proper logging framework like logger package. The comment mentions considering removal in production, but a clearer strategy would be beneficial.
| Flexible( | ||
| child: Text( | ||
| widget.project.description, | ||
| maxLines: 2, | ||
| overflow: TextOverflow.ellipsis, | ||
| style: theme.textTheme.bodyMedium?.copyWith( | ||
| height: 1.4, | ||
| fontSize: 13, | ||
| color: theme.textTheme.bodyMedium?.color | ||
| ?.withValues(alpha: 0.8), | ||
| ), | ||
| ), | ||
| ), |
There was a problem hiding this comment.
Using Flexible widget directly inside a Column without an Expanded ancestor or a constrained parent may cause layout issues. The Column has mainAxisSize: MainAxisSize.min, but the Flexible widget expects to know how much space is available. Consider using Expanded if you want the text to take available space, or remove Flexible if a fixed maxLines constraint is sufficient.
This pull request introduces several significant improvements to the project, focusing on enhanced documentation, robust error logging, architectural transparency, and database schema evolution. The main changes include the implementation of a centralized logging utility with Supabase integration, improved error handling across the data and utility layers, expanded and clarified documentation (including a detailed architecture section), and updates to the database schema to support logging and skill icon assets.
Architecture & Documentation Enhancements:
README.mdhas been substantially expanded to include a detailed architecture section, clearly explaining the MVVM + Repository Pattern, data flow, SOLID principles, design patterns, and the benefits of the chosen structure. The stack and feature descriptions have also been updated for clarity and completeness. [1] [2]Centralized Logging & Error Handling:
AppLoggerutility (lib/core/utils/app_logger.dart) that logs errors and events to a newapp_logstable in Supabase, with support for different log levels and optional user association.AppUtilsandSupabaseRepositoryto useAppLoggerfor logging exceptions, including stack traces, improving observability and debugging. [1] [2] [3] [4] [5] [6] [7] [8] [9]Database Schema Updates:
icon_assetcolumn to theskillstable to support custom icons.app_logstable with appropriate row-level security (RLS) policies to store application logs, supporting both authenticated and anonymous inserts, and granular read access for users and admins. [1] [2]Controller Improvements:
AuthControllerto check for an existing session on initialization, ensuring the UI reflects the current authentication state immediately.Miscellaneous:
AppStrings.These changes collectively improve the maintainability, observability, and clarity of the project, laying a stronger foundation for future development and team collaboration.