Skip to content

Developer#12

Merged
Franklyn-R-Silva merged 13 commits intomainfrom
developer
Dec 11, 2025
Merged

Developer#12
Franklyn-R-Silva merged 13 commits intomainfrom
developer

Conversation

@Franklyn-R-Silva
Copy link
Owner

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:

  • The README.md has 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:

  • Introduced a new AppLogger utility (lib/core/utils/app_logger.dart) that logs errors and events to a new app_logs table in Supabase, with support for different log levels and optional user association.
  • Updated error handling in AppUtils and SupabaseRepository to use AppLogger for logging exceptions, including stack traces, improving observability and debugging. [1] [2] [3] [4] [5] [6] [7] [8] [9]

Database Schema Updates:

  • Added an icon_asset column to the skills table to support custom icons.
  • Created a new app_logs table 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:

  • Enhanced AuthController to check for an existing session on initialization, ensuring the UI reflects the current authentication state immediately.

Miscellaneous:

  • Added a constant for the GitHub repositories URL in AppStrings.

These changes collectively improve the maintainability, observability, and clarity of the project, laying a stronger foundation for future development and team collaboration.

- 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.
@Franklyn-R-Silva Franklyn-R-Silva self-assigned this Dec 11, 2025
Copilot AI review requested due to automatic review settings December 11, 2025 02:45
@Franklyn-R-Silva Franklyn-R-Silva merged commit f192763 into main Dec 11, 2025
0 of 2 checks passed
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 AppLogger utility that logs errors and events to a Supabase app_logs table, 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.

Comment on lines +18 to +24
Future<void> _launchGitHub() async {
final url = Uri.parse(AppStrings.gitHubRepositoriesUrl);

if (!await launchUrl(url, mode: LaunchMode.externalApplication)) {
throw 'Could not launch $url';
}
}
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +195 to +196
onPressed: () =>
launchUrl(Uri.parse(widget.project.liveUrl!)),
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +192 to +193
onEnter: (_) => _isHovered.value = false,
onExit: (_) {},
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +7 to +28
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');
}
}
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +23
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();
}
}
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +102 to +106
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'
));
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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')
)

Copilot uses AI. Check for mistakes.
Comment on lines +87 to +90
create policy "Qualquer um pode inserir logs"
on app_logs
for insert
with check (true);
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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
)
)
);

Copilot uses AI. Check for mistakes.
// Botão de Download CV (sempre visível)
FloatingActionButton.extended(
heroTag: 'download_fab',
onPressed: () => launchUrl(Uri.parse(AppAssets.cvPtBr)),
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
} 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');
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +122 to 134
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),
),
),
),
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant