Skip to content

Desafio CoreLab Todo App - Neil Lima #79

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

Neil-Lima
Copy link

@Neil-Lima Neil-Lima commented Apr 7, 2025

Captura de Tela (243)
Olá equipe CoreLab,

Estou submetendo minha solução para o desafio técnico. Desenvolvi uma aplicação completa de gerenciamento de tarefas, incluindo todas as funcionalidades solicitadas e alguns extras.

Sobre a implementação
Optei por desenvolver um projeto integrado com frontend e backend juntos, facilitando a configuração e execução do ambiente completo. Enviei o mesmo código para ambos os repositórios (frontend e backend) para facilitar a avaliação.

Funcionalidades implementadas
CRUD completo de tarefas
Marcação de tarefas como favoritas
Definição de cores personalizadas para tarefas
Interface responsiva seguindo o mockup fornecido
Filtros por cor e favoritos
Pesquisa por texto
Tema claro/escuro
Extras implementados
Tipagens e interfaces com TypeScript
Configuração de ESLint e Prettier
Docker e Docker Compose
Testes unitários e de integração
CI/CD com GitHub Actions
Todos os detalhes da implementação estão no arquivo PULL_REQUEST.md incluído no projeto.

Agradeço a oportunidade e estou à disposição para qualquer esclarecimento.

Atenciosamente, Neil Lima

Summary by CodeRabbit

  • New Features
    • Launched the fully featured CoreLab Todo App with a modern, responsive design. Users can create, edit, delete, favorite, search, and filter tasks, plus toggle between light and dark themes.
    • Docker-based deployment support streamlines setup and consistent operation across environments.
  • Documentation
    • Updated and localized guides (in Portuguese) now provide clear setup and usage instructions.
  • Tests
    • Comprehensive testing across both frontend and backend components enhances reliability.

Victor added 2 commits April 7, 2025 13:58
Copy link

coderabbitai bot commented Apr 7, 2025

Walkthrough

This pull request introduces a complete full-stack implementation of the CoreLab Todo App. It adds extensive backend support using NestJS and MongoDB, as well as a modern React‑TypeScript frontend with multiple reusable components and style sheets. New CI/CD workflows, Docker configurations, and testing suites have been incorporated, along with comprehensive documentation updates and configuration improvements for linting, formatting, and type checking.

Changes

File(s) Change Summary
.gitattributes Added configuration (* text=auto) for LF normalization.
.github/workflows/ci.yml New CI/CD pipeline with jobs: frontend-test, backend-test, and docker-build triggered on pushes/PRs to main.
Dockerfile.backend, Dockerfile.frontend, docker-compose.yml, nginx.conf Added Dockerfiles for backend/frontend, multi‑service docker-compose setup, and Nginx proxy configuration.
PULL_REQUEST.md, README.md (root & backend) Updated documentation; README now localized to Portuguese with detailed project structure and usage instructions.
backend/(.eslintrc.js, nest-cli.json, package.json, tsconfig*.json, .prettierrc, .gitignore) New configuration files for linting, formatting, building, and project setup for the backend.
backend/src/** New NestJS backend: controllers (e.g. AppController, TodoController), services, modules, DTOs, schemas, and configuration files (e.g. CORS, database, ID formatter).
backend/test/** Introduced unit and end-to-end tests using Jest for controllers and services.
frontend/(.eslintrc, .gitignore, .prettierrc, package.json) Updated frontend config with new dependencies (e.g. React Query, axios, react-icons) and linting/formatting setup.
frontend/src/components/** New React components including App, Card, DeleteModal, SearchBar, Todo, TodoCard, TodoFilters, TodoForm, and Button with corresponding interface updates.
frontend/src/types/** Added TypeScript interfaces for component props (e.g. CardTypes, DeleteModalTypes, SearchBarTypes, TodoCardTypes, TodoFiltersTypes, TodoFormTypes, TodoTypes, ButtonTypes).
frontend/src/services/** Added service modules for handling API requests and todo CRUD operations using Axios and React Query.
frontend/src/utils/** Introduced utilities and custom hooks (e.g. useDeleteModal, TodoCardUtils, TodoFiltersUtils, TodoFormUtils, TodoUtils) to support UI and API interactions.
frontend/src/styles/** Added multiple SCSS files for global styles, theme definitions, and component-specific styling (e.g. TodoCardStyles, TodoFormStyles, TodoFiltersStyles).
src/components/Search/index.tsx, src/components/index.tsx, src/lib/api.ts Removed outdated components and API module exports.
er.name Updated Git user configuration with author details.

Sequence Diagram(s)

sequenceDiagram
    participant C as Commit/Push
    participant GH as GitHub Actions
    participant FT as Frontend Test Job
    participant BT as Backend Test Job
    participant DB as Docker Build Job

    C->>GH: Push to main / Pull Request
    GH->>FT: Run Frontend Tests
    GH->>BT: Run Backend Tests
    FT-->>GH: Test Results
    BT-->>GH: Test Results
    alt Tests Passed
        GH->>DB: Trigger Docker Build Job
    else Tests Failed
        GH->>C: Report Failure
    end
Loading
sequenceDiagram
    participant U as User
    participant F as Frontend (React)
    participant A as Axios API
    participant N as Nginx
    participant TC as TodoController
    participant TS as TodoService
    participant DB as MongoDB

    U->>F: Interact with Todo UI
    F->>A: Send API request (GET/POST/PUT/DELETE)
    A->>N: Forward Request
    N->>TC: Route to TodoController
    TC->>TS: Invoke corresponding service
    TS->>DB: Query/Update/Delete Todo
    DB-->>TS: Return Data
    TS-->>TC: Return Processed Data
    TC-->>N: Send Response
    N-->>A: Response from API
    A-->>F: Return Data
    F->>U: Update UI with response
Loading

Poem

Hop along the code trail, so fine,
New features in backend and frontend align.
CI flows and Docker dreams in every byte,
A rabbit’s heart leaps with pure delight.
Bugs scurry away in the wake of our might,
With tests and clean code shining bright! 🐰🚀


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3c54fa4 and 9a8e80f.

📒 Files selected for processing (2)
  • frontend/src/components/DeleteModal/index.tsx (1 hunks)
  • frontend/src/styles/DeleteModalStyles.scss (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • frontend/src/styles/DeleteModalStyles.scss
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/components/DeleteModal/index.tsx

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 36

🔭 Outside diff range comments (4)
er.name (1)

1-27: ⚠️ Potential issue

Remove Git configuration file from repository

This appears to be a local Git configuration file containing personal user information that should not be committed to the repository. It contains:

  1. Duplicate LFS filter settings (lines 2-5 and 15-18)
  2. Personal user information (name and email)
  3. Machine-specific paths (C:/Program Files/Git/...)

This file should be removed from version control as it:

  • Contains personal information
  • Overrides Git settings for other developers
  • Includes machine-specific configurations

Consider adding a .gitattributes file instead if you need repository-specific Git configurations.

frontend/src/pages/Vehicles/index.tsx (3)

30-43: 🛠️ Refactor suggestion

Loading state not reflected in the UI

The loading state is being tracked but not utilized in the UI. Consider adding a loading indicator when loading is true.

  return (
    <div className={styles.Vehicles}>
      <main className={styles.main}>
+       {loading ? (
+         <div className="loading">Loading vehicles...</div>
+       ) : (
        <Search placeholder="Search" value={search} onChange={() => {}} />

        <Button text="Add new vehicle" onClick={() => {}} />

        <Card title="Sandero Stepway">
          <p>Price: 22000</p>
          <p>Description: Carro usado por 2 anos...</p>
          <p>Year: 2018</p>
        </Card>
+       )}
      </main>
    </div>
  );

30-43: 🛠️ Refactor suggestion

Fetched data not displayed in UI

The component fetches vehicle data but displays hardcoded content. Consider mapping through the vehicles array to dynamically render vehicle cards.

  return (
    <div className={styles.Vehicles}>
      <main className={styles.main}>
        <Search placeholder="Search" value={search} onChange={() => {}} />

        <Button text="Add new vehicle" onClick={() => {}} />

-       <Card title="Sandero Stepway">
-         <p>Price: 22000</p>
-         <p>Description: Carro usado por 2 anos...</p>
-         <p>Year: 2018</p>
-       </Card>
+       {vehicles.length > 0 ? (
+         vehicles.map((vehicle) => (
+           <Card key={vehicle.id} title={vehicle.name}>
+             <p>Price: {vehicle.price}</p>
+             <p>Description: {vehicle.description}</p>
+             <p>Year: {vehicle.year}</p>
+           </Card>
+         ))
+       ) : (
+         <p>No vehicles found</p>
+       )}
      </main>
    </div>
  );

33-33: 🛠️ Refactor suggestion

Empty onChange handler for Search component

The Search component has an empty onChange handler, making it non-functional. Implement the search functionality:

- <Search placeholder="Search" value={search} onChange={() => {}} />
+ <Search 
+   placeholder="Search" 
+   value={search} 
+   onChange={(e) => setSearch(e.target.value)} 
+ />
🧹 Nitpick comments (93)
backend/package.json (1)

1-73: Well-structured package.json with comprehensive configuration

The package.json contains all necessary configurations for a NestJS application with MongoDB integration, including appropriate scripts, dependencies, and test setup.

Consider these minor improvements:

  • Add meaningful values for the empty description and author fields (lines 4-5)
  • Consider updating Mongoose from v7.0.0 to the latest major version (v8.x) for potential performance improvements and new features
backend/README.md (4)

31-33: Command Examples: Consideration for Shell Prompts

The command examples (lines 31–33) display a $ prompt (e.g., $ npm install). While common in shell examples, some linting guidelines suggest removing the prompt for ease of copy-paste. If this is intentional for clarity, you may ignore this; otherwise, consider removing the $ to improve usability.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

32-32: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)


67-70: Deployment Commands: Shell Prompt Consistency

Similar to the installation command block, the deployment commands (lines 67–70) include a $ prompt. Consider either removing the prompt for direct copy-paste compatibility or adding a note that the prompt is not part of the command.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

68-68: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)


69-69: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)


74-78: Tone Adjustment: Replace Colloquial Expression

In the Resources section (line 76), the phrase “come in handy” is somewhat casual. Consider using a more formal alternative (e.g., “are useful” or “can be beneficial”) to maintain a professional tone.

🧰 Tools
🪛 LanguageTool

[style] ~76-~76: The expression “come in handy” is rather colloquial. Consider replacing it to add a more formal tone to your writing.
Context: ...ces Check out a few resources that may come in handy when working with NestJS: - Visit the ...

(COME_IN_HANDY)


88-90: Language Refinement: Adjust Adjectives in the Support Section

On line 89, the phrase “the amazing backers” is used. To achieve a more formal tone, consider replacing “amazing” with a term like “valued” or “dedicated.” Additionally, review any compound adjective usage to ensure proper hyphenation if needed.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~89-~89: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...). ## Support Nest is an MIT-licensed open source project. It can grow thanks to the spon...

(EN_COMPOUND_ADJECTIVE_INTERNAL)


[style] ~89-~89: Consider using a more formal and expressive alternative to ‘amazing’.
Context: ...anks to the sponsors and support by the amazing backers. If you'd like to join them, pl...

(AWESOME)

frontend/src/App.tsx (1)

1-1: Consider fixing formatting issues instead of disabling ESLint.

Rather than disabling the prettier/prettier rule, consider fixing the formatting issues to maintain consistent code style throughout the project.

frontend/src/utils/DeleteModalUtils.tsx (2)

1-1: Consider fixing formatting issues instead of disabling ESLint.

Rather than disabling the prettier/prettier rule, consider fixing the formatting issues to maintain consistent code style throughout the project.


2-6: Consider the necessity of this abstraction layer.

This utility function is a thin wrapper around the service function and doesn't add much functionality. Consider whether this abstraction layer provides enough value or if calling the service directly would be more straightforward.

If the wrapper exists to centralize error handling or provide additional business logic in the future, that would justify its existence.

backend/src/config/databaseConfig.ts (1)

1-1: Consider fixing formatting issues instead of disabling ESLint.

Rather than disabling the prettier/prettier rule, consider fixing the formatting issues to maintain consistent code style throughout the project.

frontend/src/services/DeleteModalServices.tsx (1)

1-1: Consider addressing formatting issues instead of disabling ESLint rules.

Rather than disabling the prettier/prettier rule, it would be better to fix the formatting issues that are causing the rule to trigger.

frontend/src/components/index.tsx (1)

1-1: Consider addressing formatting issues instead of disabling ESLint rules.

Rather than disabling the prettier/prettier rule globally, it would be better to fix the formatting issues that are causing the rule to trigger.

backend/src/config/corsConfig.ts (1)

1-1: Consider addressing formatting issues instead of disabling ESLint rules.

Rather than disabling the prettier/prettier rule, fix the formatting issues that are causing the rule to trigger.

frontend/src/types/TodoTypes.tsx (1)

1-8: Consider using string for id when working with MongoDB

The interface looks well-structured for a todo item. However, I noticed you're using a number type for the id property. If you're working with MongoDB (as indicated in the PR description), consider using string instead since MongoDB uses string ObjectIds by default.

export interface ITodo {
-  id: number;
+  id: string;
  title: string;
  description: string;
  isFavorite: boolean;
  color: string;
  createdAt: Date;
} 
backend/src/app.module.ts (2)

1-1: Remove ESLint disable comment

Using ESLint disable comments should be avoided when possible. Instead, fix the formatting issues or configure your ESLint rules appropriately.

-/* eslint-disable prettier/prettier */

12-13: Add trailing newline at end of file

Files should end with a newline character as per common coding standards. This helps prevent issues with certain tools and makes diffs cleaner.

export class AppModule {}
+
Dockerfile.backend (3)

1-2: Consider using a more specific Node version

Using node:16-alpine is good for keeping the image size small, but consider pinning to a specific version (e.g., node:16.20-alpine) to ensure consistent builds.


9-10: Consider using .dockerignore

To optimize the build process, consider adding a .dockerignore file to exclude unnecessary files like node_modules, dist, etc.


13-15: Consider using a non-root user for better security

For better security, consider adding a user and running the application as a non-root user.

EXPOSE 3333

+# Create a non-root user and switch to it
+RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -G nodejs
+USER nodejs

CMD ["npm", "run", "start:prod"]
frontend/src/styles/theme.scss (2)

1-2: Remove eslint-disable comment

Instead of disabling the prettier/eslint rule, consider formatting the file according to the project's standards.


26-46: Consider using CSS custom properties efficiently

Your light theme implementation is clean. For better maintenance, consider only overriding the variables that actually change between themes, rather than redefining all properties.

For example, the accent colors stay the same between themes, so they could be excluded from the light-mode override:

body.light-mode {
  --bg-primary: #f5f5f5;
  --bg-secondary: #ffffff;
  --bg-tertiary: #e0e0e0;
  --text-primary: #333333;
  --text-secondary: #666666;
-  --accent-primary: #4caf50;
-  --accent-secondary: #3d8b40;
-  --accent-tertiary: #2e7d32;
-  --error: #f44336;
-  --error-dark: #d32f2f;
  --border-color: #dddddd;
  // ...rest of the changes
}
frontend/src/utils/useDeleteModal.tsx (2)

1-1: Remove the ESLint disable comment

Instead of disabling ESLint rules globally for the file, it would be better to fix the underlying formatting issues that are triggering the warnings.

-/* eslint-disable prettier/prettier */

4-15: LGTM! Well-structured custom hook

The useDeleteModal hook follows React best practices by clearly encapsulating modal state management and providing a clean API with descriptive function names.

 };
-}; 
+};

Remove the trailing space at the end to avoid Prettier warnings.

frontend/src/types/DeleteModalTypes.tsx (1)

1-6: Consider changing file extension and adding documentation

The interface is well-structured with appropriate property types, but there are a couple of improvements to consider.

Since this file only contains TypeScript types and no JSX, consider:

  1. Changing the file extension from .tsx to .ts
  2. Adding JSDoc comments for better documentation:
+/**
+ * Props for the DeleteModal component
+ */
 export interface DeleteModalProps {
+  /** Whether the modal is currently visible */
   isOpen: boolean;
+  /** The title text to display in the modal */
   title: string;
+  /** Function called when user confirms deletion */
   onConfirm: () => void;
+  /** Function called when user cancels deletion */
   onCancel: () => void;
-} 
+}
backend/src/modules/todos/dto/update-todo.dto.ts (2)

1-1: Remove the ESLint disable comment

Instead of disabling ESLint rules globally for the file, it would be better to fix the underlying formatting issues that are triggering the warnings.

-/* eslint-disable prettier/prettier */

4-20: Well-structured DTO with proper validation

The UpdateTodoDto class correctly implements partial updates with appropriate validation decorators. The use of @IsOptional() allows for updating individual fields without requiring all properties.

Consider adding JSDoc documentation for improved code readability:

+/**
+ * Data Transfer Object for updating Todo items
+ */
 export class UpdateTodoDto {
+  /** Optional title for the Todo item */
   @IsOptional()
   @IsString()
   title?: string;

+  /** Optional description for the Todo item */
   @IsOptional()
   @IsString()
   description?: string;

+  /** Optional flag to mark Todo as favorite */
   @IsOptional()
   @IsBoolean()
   isFavorite?: boolean;

+  /** Optional color code for the Todo item */
   @IsOptional()
   @IsString()
   color?: string;
-} 
+}
backend/src/modules/todos/dto/create-todo.dto.ts (2)

1-1: Remove the ESLint disable comment

This comment should be removed, and instead, the formatting issues should be fixed to comply with the project's linting rules.

-/* eslint-disable prettier/prettier */

17-19: Consider adding more specific validation for the color property

The color property is currently only validated as a non-empty string. Consider adding pattern validation to ensure it follows a valid color format (like hex code).

@IsNotEmpty()
@IsString()
+@Matches(/^#[0-9A-Fa-f]{6}$/, { message: 'Color must be a valid hex color code' })
color: string;
backend/src/modules/todos/module/todo.module.ts (1)

1-1: Remove the ESLint disable comment

This comment should be removed, and instead, the formatting issues should be fixed to comply with the project's linting rules.

-/* eslint-disable prettier/prettier */
backend/src/modules/todos/interfaces/todo.interface.ts (3)

1-1: Remove unnecessary ESLint disable comment.

The ESLint disable comment for prettier/prettier should be removed unless there's a specific formatting issue that can't be resolved.

-/* eslint-disable prettier/prettier */

4-10: Consider adding JSDoc comments to improve documentation.

The Todo interface is well-structured, but adding JSDoc comments would improve documentation and provide more context about each property's purpose.

+/**
+ * Interface representing a Todo item
+ */
 export interface Todo {
+  /** Title of the todo item */
   title: string;
+  /** Detailed description of the todo item */
   description: string;
+  /** Flag indicating if the todo is marked as favorite */
   isFavorite: boolean;
+  /** Color code for the todo item */
   color: string;
+  /** Creation timestamp of the todo item */
   createdAt: Date;
 }

12-12: Add JSDoc comment to explain the purpose of the TodoDocument interface.

The empty interface extension pattern is common in Mongoose, but a comment would clarify its purpose for other developers.

+/**
+ * Interface that extends the Todo interface with Mongoose Document properties
+ * for database operations and document methods
+ */
 export interface TodoDocument extends Todo, Document {} 
frontend/src/components/Card/index.tsx (1)

5-5: Use destructuring for props to improve readability.

Destructuring the props in the function parameters would make the component more readable and reduce the need for props. prefix in the JSX.

-const Card = (props: ICardProps) => {
+const Card: React.FC<ICardProps> = ({ title, children }) => {

Also, update the JSX to use the destructured props:

   return (
     <div className={styles.Card}>
-      <h2>{props.title}</h2>
+      <h2>{title}</h2>

       <div className={styles.content}>
-        {props.children}
+        {children}
       </div>
     </div>
   );
frontend/src/components/SearchBar/index.tsx (2)

1-1: Remove unnecessary ESLint disable comment.

The ESLint disable comment for prettier/prettier should be removed unless there's a specific formatting issue that can't be resolved.

-/* eslint-disable prettier/prettier */

5-9: Consider moving the interface to a dedicated types file.

The Card component imports its props interface from a central types file, but the SearchBar defines its interface locally. Consider moving this interface to a dedicated types file for consistency.

-interface SearchBarProps {
-  value: string;
-  onChange: (value: string) => void;
-  placeholder?: string;
-}

Create a new file at src/types/SearchBarTypes.tsx:

export interface SearchBarProps {
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
}

Then import it in this file:

 import React from 'react';
 import '../../styles/SearchBarStyles.scss';
+import { SearchBarProps } from '../../types/SearchBarTypes';
frontend/src/services/TodoCardServices.tsx (1)

1-10: Well-structured service functions with proper typing.

The TodoCardServices implementation provides clean, focused functions for toggling favorites and deleting todos. The return type Promise properly indicates that toggleFavorite returns the updated todo object, while Promise correctly shows that deleteTodo doesn't return data.

Consider adding error handling to these functions to gracefully manage API failures rather than letting errors propagate to components.

Here's how you could improve error handling:

 export const toggleFavorite = async (id: number, isFavorite: boolean): Promise<ITodo> => {
-  return put(`/todos/${id}`, { isFavorite });
+  try {
+    return await put(`/todos/${id}`, { isFavorite });
+  } catch (error) {
+    console.error(`Failed to toggle favorite for todo ${id}:`, error);
+    throw error;
+  }
 };

 export const deleteTodo = async (id: number): Promise<void> => {
-  return del(`/todos/${id}`);
+  try {
+    return await del(`/todos/${id}`);
+  } catch (error) {
+    console.error(`Failed to delete todo ${id}:`, error);
+    throw error;
+  }
 }; 
frontend/src/services/TodoFormServices.tsx (1)

1-10: Well-implemented service functions with proper TypeScript usage.

Good use of TypeScript features:

  • Omit<ITodo, 'id' | 'createdAt'> correctly ensures that the client doesn't provide server-generated fields when creating todos
  • Partial<ITodo> appropriately allows updating only specific fields of a todo item

As with the TodoCardServices, consider adding error handling to gracefully manage API failures.

 export const createTodo = async (todo: Omit<ITodo, 'id' | 'createdAt'>): Promise<ITodo> => {
-  return post('/todos', todo);
+  try {
+    return await post('/todos', todo);
+  } catch (error) {
+    console.error('Failed to create todo:', error);
+    throw error;
+  }
 };

 export const updateTodo = async (id: number, todo: Partial<ITodo>): Promise<ITodo> => {
-  return put(`/todos/${id}`, todo);
+  try {
+    return await put(`/todos/${id}`, todo);
+  } catch (error) {
+    console.error(`Failed to update todo ${id}:`, error);
+    throw error;
+  }
 }; 
backend/src/main.ts (2)

1-1: Remove unnecessary ESLint disable comment.

This ESLint disable directive suggests there are formatting issues that should be fixed rather than suppressed.

-/* eslint-disable prettier/prettier */

7-20: Good NestJS setup, but consider environment configuration.

The bootstrap function correctly sets up the NestJS application with proper validation pipes and CORS configuration. However, hardcoding the port (3333) limits flexibility across different environments.

Consider using environment variables for configuration:

 async function bootstrap() {
   const app = await NestFactory.create(AppModule);
   
   // Configuração de validação global
   app.useGlobalPipes(new ValidationPipe({
     whitelist: true,
     transform: true,
   }));
   
   // Configuração de CORS
   app.enableCors(corsConfig);
   
-  await app.listen(3333);
+  const port = process.env.PORT || 3333;
+  await app.listen(port);
+  console.log(`Application is running on: http://localhost:${port}`);
 }

Additionally, consider adding error handling:

 async function bootstrap() {
-  const app = await NestFactory.create(AppModule);
-  
-  // Configuração de validação global
-  app.useGlobalPipes(new ValidationPipe({
-    whitelist: true,
-    transform: true,
-  }));
-  
-  // Configuração de CORS
-  app.enableCors(corsConfig);
-  
-  await app.listen(3333);
+  try {
+    const app = await NestFactory.create(AppModule);
+    
+    // Configuração de validação global
+    app.useGlobalPipes(new ValidationPipe({
+      whitelist: true,
+      transform: true,
+    }));
+    
+    // Configuração de CORS
+    app.enableCors(corsConfig);
+    
+    const port = process.env.PORT || 3333;
+    await app.listen(port);
+    console.log(`Application is running on: http://localhost:${port}`);
+  } catch (error) {
+    console.error('Failed to start application:', error);
+    process.exit(1);
+  }
 }
backend/src/modules/todos/schemas/todo.schema.ts (3)

1-1: Remove the eslint-disable comment or address the underlying formatting issues.

Instead of disabling the Prettier rules globally for the file, fix the underlying formatting issues or configure Prettier settings properly in the project.

-/* eslint-disable prettier/prettier */

18-19: Consider adding color validation.

The color field is required but doesn't have any validation for the format or allowed values. Consider adding validation to ensure it follows a valid format (e.g., hex code, named color).

@Prop({ required: true })
-  color: string;
+  @Prop({ 
+    required: true,
+    validate: {
+      validator: (v: string) => /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(v),
+      message: props => `${props.value} is not a valid hex color!`
+    } 
+  })
+  color: string;

25-25: Remove trailing whitespace at end of line.

There's a trailing space at the end of line 25 after "Todo;".

-export const TodoSchema = SchemaFactory.createForClass(Todo); 
+export const TodoSchema = SchemaFactory.createForClass(Todo);
Dockerfile.frontend (2)

13-19: Consider adding security improvements to the Nginx container.

The Nginx container configuration could benefit from security enhancements like running as a non-root user and adding a health check.

FROM nginx:alpine

COPY --from=build /app/build /usr/share/nginx/html

COPY nginx.conf /etc/nginx/conf.d/default.conf

+# Create a non-root user
+RUN addgroup -g 1001 -S app && \
+    adduser -u 1001 -S app -G app && \
+    chown -R app:app /usr/share/nginx/html
+
+# Switch to non-root user
+USER app
+
+# Add healthcheck
+HEALTHCHECK --interval=30s --timeout=3s CMD wget --quiet --tries=1 --spider http://localhost:80/ || exit 1

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

21-21: Remove trailing whitespace at end of line.

There's a trailing space at the end of line 21.

-CMD ["nginx", "-g", "daemon off;"] 
+CMD ["nginx", "-g", "daemon off;"]
frontend/src/components/DeleteModal/index.tsx (3)

1-1: Remove the eslint-disable comment.

Instead of disabling the Prettier rules for the entire file, fix the underlying formatting issues or configure Prettier settings properly in the project.

-/* eslint-disable prettier/prettier */

12-13: Consider implementing internationalization for text content.

The modal text is hardcoded in Portuguese. Consider implementing an internationalization solution for better maintainability and language support.


27-27: Remove trailing whitespace at end of line.

There's a trailing space at the end of line 27.

-export default DeleteModal; 
+export default DeleteModal;
frontend/src/pages/Vehicles/index.tsx (1)

28-28: Remove console.log statement

This console.log statement should be removed before production deployment.

-  console.log({ vehicles });
docker-compose.yml (3)

14-27: Add health checks for backend service

Consider adding health checks to ensure the service is fully initialized before dependent services try to connect:

  backend:
    build:
      context: .
      dockerfile: Dockerfile.backend
    container_name: backend
    ports:
      - "3333:3333"
    environment:
      - NODE_ENV=production
      - MONGODB_URI=mongodb://mongodb:27017/todolist_db
    depends_on:
      - mongodb
+   healthcheck:
+     test: ["CMD", "curl", "-f", "http://localhost:3333/health"]
+     interval: 30s
+     timeout: 10s
+     retries: 3
+     start_period: 40s
    networks:
      - app-network

14-27: Add restart policy for production resilience

For production environments, it's important to define restart policies to ensure services recover from failures:

  backend:
    build:
      context: .
      dockerfile: Dockerfile.backend
    container_name: backend
+   restart: unless-stopped
    ports:
      - "3333:3333"

46-46: Fix file ending

The file has trailing spaces and no newline at the end. This should be fixed:

- volumes:
-  mongodb_data: 
+ volumes:
+  mongodb_data:
🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 46-46: no new line character at the end of file

(new-line-at-end-of-file)


[error] 46-46: trailing spaces

(trailing-spaces)

frontend/src/styles/global.scss (2)

1-1: Consider removing ESLint disable comment

Instead of disabling Prettier formatting for the entire file, consider configuring Prettier to handle SCSS files correctly.


59-59: Add newline at end of file

Add a newline at the end of the file to comply with standard coding practices:

.modal {
  animation: fadeIn 0.3s ease-out;
-} 
+}
+
frontend/src/services/TodoServices.tsx (2)

1-16: Consider caching strategy and error handling improvements

The React Query implementation follows best practices by using query keys and separating the data fetching logic from the hook. However:

  1. Setting both staleTime and gcTime to 0 might lead to unnecessary network requests - consider if some minimal caching would improve performance
  2. There's no error handling in the getTodos function
export const getTodos = async (): Promise<ITodo[]> => {
-  return get('/todos');
+  try {
+    return await get('/todos');
+  } catch (error) {
+    console.error('Failed to fetch todos:', error);
+    throw error;
+  }
};

export const useTodos = () => {
  return useQuery<ITodo[], Error>({
    queryKey: ['todos'],
    queryFn: getTodos,
-    staleTime: 0, // Sempre considerar os dados como obsoletos
-    gcTime: 0  // Não manter em cache
+    staleTime: 30000, // Consider data stale after 30 seconds
+    gcTime: 300000  // Keep unused data in cache for 5 minutes
  });
};

18-20: Improve type safety for queryClient parameter

The queryClient parameter is typed as any, which reduces type safety. Consider using the proper type from React Query.

-export const invalidateTodosCache = (queryClient: any) => {
+import { QueryClient } from '@tanstack/react-query';
+
+export const invalidateTodosCache = (queryClient: QueryClient) => {
  queryClient.invalidateQueries(['todos']);
};
frontend/src/lib/api.ts (1)

9-9: Remove unused endpoint function

The endpoint function is defined but not used anywhere in the file.

-const endpoint = (path: string): string => API + path;
frontend/src/utils/TodoCardUtils.tsx (1)

12-18: Avoid redundant Date object creation

Creating a new Date from an existing Date object is unnecessary and potentially introduces bugs if the input isn't actually a Date object.

export const formatDate = (date: Date): string => {
-  return new Date(date).toLocaleDateString('pt-BR', {
+  return date.toLocaleDateString('pt-BR', {
    day: 'numeric',
    month: 'short',
    year: 'numeric'
  });
};
frontend/src/components/DeleteModal/DeleteModalStyles.scss (1)

33-64: Consider using SCSS variables for colors.

While the button styling is well-implemented with appropriate visual distinction and hover effects, consider using SCSS variables for colors to improve maintainability and consistency throughout the application.

+ // At the top of the file or in a separate variables file
+ $cancel-bg: #e0e0e0;
+ $cancel-hover: #d0d0d0;
+ $confirm-bg: #dc3545;
+ $confirm-hover: #c82333;
+ $text-dark: #333;
+ $text-medium: #666;

  &.cancel-button {
-     background-color: #e0e0e0;
-     color: #333;
+     background-color: $cancel-bg;
+     color: $text-dark;

      &:hover {
-       background-color: #d0d0d0;
+       background-color: $cancel-hover;
      }
  }

  &.confirm-button {
-     background-color: #dc3545;
+     background-color: $confirm-bg;
      color: white;

      &:hover {
-       background-color: #c82333;
+       background-color: $confirm-hover;
      }
  }
backend/src/config/id-formatter.ts (3)

1-3: Remove unnecessary ESLint disable comment.

Instead of disabling ESLint rules, consider fixing the underlying formatting issues to maintain code quality standards.

- /* eslint-disable prettier/prettier */
  import { Types } from 'mongoose';

32-37: Remove ESLint disable comment in toNumber method.

Rather than disabling the ESLint rule, rename the parameter to remove the underscore since it is being used.

- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- static toNumber(_id: Types.ObjectId): number {
+ static toNumber(id: Types.ObjectId): number {
    // Use the ObjectId timestamp to generate a unique ID
    // Usar o timestamp do ObjectId para gerar um ID único
-   const timestamp = _id.getTimestamp().getTime();
+   const timestamp = id.getTimestamp().getTime();
    return timestamp;
  }

4-38: Consider using standalone functions instead of a static-only class.

As noted by static analysis, classes with only static methods can be replaced with standalone functions, which is generally considered better practice in TypeScript/JavaScript.

- export class IdFormatter {
-   static toObjectId(id: string | number): Types.ObjectId {
+ export function toObjectId(id: string | number): Types.ObjectId {
    // Implementation...
  }

-   static toString(id: Types.ObjectId): string {
+ export function toString(id: Types.ObjectId): string {
    return id.toString();
  }

-   static toNumber(_id: Types.ObjectId): number {
+ export function toNumber(id: Types.ObjectId): number {
    // Implementation...
  }
- }
🧰 Tools
🪛 Biome (1.9.4)

[error] 4-38: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

frontend/src/styles/TodoFormStyles.scss (2)

1-1: Remove ESLint disable comment.

The ESLint disable comment for prettier at the top of the file should be removed. Instead, configure your project's ESLint and Prettier settings properly to work together without needing to disable rules.

-/* eslint-disable prettier/prettier */

5-13: Extract color values as SCSS variables.

The colors defined in the COLORS array in TodoFormUtils.tsx should be consistent with these styles. Consider extracting these color values as SCSS variables in your theme file to ensure consistency across your application.

+ // In theme.scss
+ $color-red: #f44336;
+ $color-orange: #ff9800;
+ $color-yellow: #ffeb3b;
+ $color-green: #4caf50;
+ $color-blue: #2196f3;
+ $color-purple: #9c27b0;
+ $color-brown: #795548;
frontend/src/index.tsx (1)

1-1: Remove ESLint disable comment.

The ESLint disable comment for prettier at the top of the file should be removed. Instead, configure your project's ESLint and Prettier settings properly to work together.

-/* eslint-disable prettier/prettier */
frontend/src/components/TodoForm/index.tsx (2)

43-55: Improve color selector accessibility.

While the color selector looks good visually, it lacks proper accessibility attributes. Users with screen readers might have difficulty understanding which color is selected.

<div
  key={c}
  className={`color-option ${color === c ? 'color-option--selected' : ''}`}
  style={{ backgroundColor: c }}
  onClick={() => setColor(c)}
+ aria-label={`Color ${COLORS.indexOf(c) + 1}`}
+ role="radio"
+ aria-checked={color === c}
/>

Also consider adding a tooltip or some other indication of what each color represents.


57-66: Improve checkbox accessibility and styling.

The checkbox for marking a task as favorite could benefit from improved styling and accessibility.

<div className="form-group">
-  <label>
+  <label htmlFor="favorite" className="checkbox-label">
    <input
+     id="favorite"
      type="checkbox"
      checked={isFavorite}
      onChange={(e) => setIsFavorite(e.target.checked)}
+     aria-label="Mark as favorite"
    />
    {' '}Marcar como favorito
  </label>
</div>
frontend/src/utils/TodoFormUtils.tsx (2)

30-44: Add form reset after submission.

The form currently doesn't reset after submission. Consider adding a reset function to clear the form fields after a successful submission for better user experience, especially when creating multiple todos.

const handleSubmit = (e: React.FormEvent, onSave: (todo: Omit<ITodo, 'id' | 'createdAt'>) => void) => {
  e.preventDefault();
  
  if (!title.trim()) {
    alert('O título é obrigatório!');
    return;
  }
  
  onSave({
    title,
    description,
    color,
    isFavorite,
  });
+  
+  // Reset form if not editing (no todo provided)
+  if (!todo) {
+    setTitle('');
+    setDescription('');
+    setColor(COLORS[0]);
+    setIsFavorite(false);
+  }
};

5-13: Consider making COLORS enum or object for better typing.

The COLORS array is well-defined, but consider using an enum or an object with named color values for better type safety and readability in the codebase.

-export const COLORS = [
-  '#f44336', // Vermelho
-  '#ff9800', // Laranja
-  '#ffeb3b', // Amarelo
-  '#4caf50', // Verde
-  '#2196f3', // Azul
-  '#9c27b0', // Roxo
-  '#795548', // Marrom
-];
+export enum TodoColor {
+  RED = '#f44336',
+  ORANGE = '#ff9800',
+  YELLOW = '#ffeb3b',
+  GREEN = '#4caf50',
+  BLUE = '#2196f3',
+  PURPLE = '#9c27b0',
+  BROWN = '#795548'
+}
+
+export const COLORS = Object.values(TodoColor);

This approach would allow you to use TodoColor.RED in your code for better readability and type checking.

backend/test/todo.service.spec.ts (1)

66-68: Improve test assertion specificity

The current test verifies the length is greater than 0, but a more precise assertion would check for the exact expected output.

  const result = await service.findAll();
- expect(result.length).toBeGreaterThan(0);
+ expect(result).toEqual(mockTodos);
  expect(mockTodoModel.find).toHaveBeenCalled();
frontend/src/components/TodoCard/index.tsx (3)

1-1: Avoid global ESLint disabling

It's better to address specific linting issues rather than disabling prettier entirely. Consider fixing the specific formatting issues.

- /* eslint-disable prettier/prettier */
+ // Fix specific linting issues instead of disabling prettier

37-39: Enhance accessibility for favorite button

Using star symbols (★/☆) may not be sufficient for screen readers. Consider adding a more descriptive visual indicator along with the aria-label.

  <button 
    className={`favorite-button ${isFavorite ? 'is-favorite' : ''}`}
    onClick={() => onToggleFavorite(id, !isFavorite)}
    aria-label={isFavorite ? 'Remover dos favoritos' : 'Adicionar aos favoritos'}
  >
-   {isFavorite ? '★' : '☆'}
+   <span className="sr-only">{isFavorite ? 'Favorito' : 'Não favorito'}</span>
+   <span aria-hidden="true">{isFavorite ? '★' : '☆'}</span>
  </button>

57-65: Enhance accessibility for action buttons

Replace emoji characters with more accessible icon solutions for edit and delete buttons.

  <button 
    className="edit-button"
    onClick={() => onEdit(todo)}
    aria-label="Editar tarefa"
  >
-   ✏️
+   <span aria-hidden="true" className="edit-icon">✏️</span>
+   <span className="sr-only">Editar</span>
  </button>
  <button 
    className="delete-button"
    onClick={openModal}
    aria-label="Excluir tarefa"
  >
-   🗑️
+   <span aria-hidden="true" className="delete-icon">🗑️</span>
+   <span className="sr-only">Excluir</span>
  </button>
frontend/src/components/TodoFilters/index.tsx (1)

25-41: Improve color filter accessibility

The color options may not be accessible to users with color blindness. Consider adding patterns or labels to distinguish colors beyond just visual differences.

  <div className="color-filters">
    <div
      className={`color-option ${selectedColor === null ? 'color-option--selected' : ''}`}
      style={{ background: 'linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet)' }}
      onClick={() => onColorSelect(null)}
      title="Todas as cores"
+     role="button"
+     tabIndex={0}
+     aria-pressed={selectedColor === null}
    />
    {COLORS.map((color) => (
      <div
        key={color}
        className={`color-option ${selectedColor === color ? 'color-option--selected' : ''}`}
        style={{ backgroundColor: color }}
        onClick={() => onColorSelect(color)}
        title={color}
+       role="button"
+       tabIndex={0}
+       aria-pressed={selectedColor === color}
      />
    ))}
  </div>
.github/workflows/ci.yml (2)

72-75: Add more descriptive job name

The job name 'docker-build' could be more descriptive to indicate it's a deployment step.

- docker-build:
+ deploy-docker-images:
  needs: [frontend-test, backend-test]
  if: github.ref == 'refs/heads/main'
  runs-on: ubuntu-latest

1-97: Clean up trailing spaces and add newline at end of file

The YAML file contains numerous trailing spaces and is missing a newline at the end, which could cause issues with some tools.

Use an editor configuration or linting tool like EditorConfig or Prettier to automatically clean up trailing spaces and ensure files end with a newline.

🧰 Tools
🪛 actionlint (1.7.4)

14-14: the runner of "actions/checkout@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


17-17: the runner of "actions/setup-node@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


45-45: the runner of "actions/checkout@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


48-48: the runner of "actions/setup-node@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


78-78: the runner of "actions/checkout@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


81-81: the runner of "docker/setup-buildx-action@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


84-84: the runner of "docker/build-push-action@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


92-92: the runner of "docker/build-push-action@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🪛 YAMLlint (1.35.1)

[error] 15-15: trailing spaces

(trailing-spaces)


[error] 20-20: trailing spaces

(trailing-spaces)


[error] 25-25: trailing spaces

(trailing-spaces)


[error] 30-30: trailing spaces

(trailing-spaces)


[error] 35-35: trailing spaces

(trailing-spaces)


[error] 46-46: trailing spaces

(trailing-spaces)


[error] 51-51: trailing spaces

(trailing-spaces)


[error] 56-56: trailing spaces

(trailing-spaces)


[error] 61-61: trailing spaces

(trailing-spaces)


[error] 66-66: trailing spaces

(trailing-spaces)


[error] 79-79: trailing spaces

(trailing-spaces)


[error] 82-82: trailing spaces

(trailing-spaces)


[error] 90-90: trailing spaces

(trailing-spaces)


[error] 97-97: no new line character at the end of file

(new-line-at-end-of-file)


[error] 97-97: trailing spaces

(trailing-spaces)

frontend/src/styles/TodoFiltersStyles.scss (2)

1-1: Consider removing eslint-disable comment

This eslint-disable comment for Prettier might not be necessary if you configure your ESLint and Prettier properly to work together. Consider removing it or addressing the underlying formatting issues.

-/* eslint-disable prettier/prettier */

38-56: Consider adding keyboard accessibility for color options

The color options are only accessible via mouse clicks. Consider enhancing accessibility by adding keyboard navigation support.

.color-option {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  cursor: pointer;
  transition: all 0.3s;
  border: 2px solid transparent;
  box-shadow: 0 2px 5px var(--shadow-color);
+  outline: none;
  
  &:hover {
    transform: scale(1.1);
    box-shadow: 0 4px 10px var(--shadow-color);
  }
  
+  &:focus-visible {
+    border-color: var(--text-primary);
+    box-shadow: 0 0 0 2px var(--accent-primary), 0 4px 10px var(--shadow-color);
+  }
  
  &--selected {
    border-color: var(--text-primary);
    box-shadow: 0 0 0 2px var(--accent-primary), 0 4px 10px var(--shadow-color);
  }
}
frontend/src/components/Todo/index.tsx (4)

1-1: Remove eslint-disable comment

Rather than disabling Prettier, consider configuring your ESLint and Prettier to work together properly.

-/* eslint-disable prettier/prettier */

28-33: Use combined state update

Instead of maintaining separate todos and filteredTodos states that need to be synchronized, consider deriving filteredTodos directly from todosData in the filtering effect.

// Atualizar o estado local quando os dados do React Query forem carregados
-useEffect(() => {
-  if (todosData) {
-    setTodos(todosData);
-  }
-}, [todosData]);

Then modify the filtering effect:

// Aplicar filtros
useEffect(() => {
-  let result = [...todos];
+  if (!todosData) return;
+  let result = [...todosData];
  
  // Rest of the filtering logic...
  
  setFilteredTodos(result);
-}, [todos, selectedColor, showOnlyFavorites, searchQuery]);
+}, [todosData, selectedColor, showOnlyFavorites, searchQuery]);

104-143: Extract reusable cache update logic

The cache update logic is duplicated between creating and updating todos. Consider extracting this to a reusable function.

+const updateQueryCache = (updatedTodo: ITodo, isNew = false) => {
+  // Update the React Query cache
+  queryClient.setQueryData(['todos'], (oldData: ITodo[] | undefined) => {
+    if (!oldData) return isNew ? [updatedTodo] : [];
+    return isNew 
+      ? [...oldData, updatedTodo]
+      : oldData.map(todo => todo.id === updatedTodo.id ? updatedTodo : todo);
+  });
+  
+  // Invalidate the cache to force a new fetch
+  invalidateTodosCache(queryClient);
+  
+  // Update the local state
+  setTodos(prev => isNew 
+    ? [...prev, updatedTodo]
+    : prev.map(todo => todo.id === updatedTodo.id ? updatedTodo : todo)
+  );
+};

const handleSave = async (todoData: Omit<ITodo, 'id' | 'createdAt'>) => {
  try {
    if (currentTodo) {
      // Update existing todo
      const updatedTodo = await TodoFormUtils.updateExistingTodo(currentTodo.id, todoData);
-      
-      // Update the React Query cache
-      queryClient.setQueryData(['todos'], (oldData: ITodo[] | undefined) => {
-        if (!oldData) return [];
-        return oldData.map(todo => todo.id === currentTodo.id ? updatedTodo : todo);
-      });
-      
-      // Invalidate the cache to force a new fetch
-      invalidateTodosCache(queryClient);
-      
-      // Update the local state
-      setTodos(prev => prev.map(todo => todo.id === currentTodo.id ? updatedTodo : todo));
+      updateQueryCache(updatedTodo);
    } else {
      // Create new todo
      const newTodo = await TodoFormUtils.createNewTodo(todoData);
-      
-      // Update the React Query cache
-      queryClient.setQueryData(['todos'], (oldData: ITodo[] | undefined) => {
-        if (!oldData) return [newTodo];
-        return [...oldData, newTodo];
-      });
-      
-      // Invalidate the cache to force a new fetch
-      invalidateTodosCache(queryClient);
-      
-      // Update the local state
-      setTodos(prev => [...prev, newTodo]);
+      updateQueryCache(newTodo, true);
    }
    
    setIsModalOpen(false);
    setCurrentTodo(undefined);
  } catch (error) {
    console.error('Erro ao salvar tarefa:', error);
+    // Add user-facing error message
  }
};

203-205: Use i18n for text messages

Consider using an internationalization library instead of hardcoding Portuguese text to make it easier to support multiple languages consistently.

<p style={{ color: 'var(--text-primary)', textAlign: 'center' }}>
-  Nenhuma tarefa encontrada.
+  {t('no_tasks_found', 'No tasks found.')}
</p>
frontend/src/styles/SearchBarStyles.scss (2)

1-1: Remove eslint-disable comment

Rather than disabling Prettier, configure your ESLint and Prettier to work together properly.

-/* eslint-disable prettier/prettier */

4-38: Remove duplicate search component styles

There are two similar search components with different styles (.search-bar and .search-container). Consider consolidating them into a single reusable component with variants if needed.

Also applies to: 40-87

frontend/src/styles/TodoStyles.scss (1)

1-1: Remove eslint-disable comment

Rather than disabling Prettier, configure your ESLint and Prettier to work together properly.

-/* eslint-disable prettier/prettier */
README.md (2)

49-51: Add language specifiers to code blocks for better syntax highlighting and readability.

The Markdown code blocks throughout the document are missing language specifiers, which would enable syntax highlighting. This is particularly important for command blocks.

Update the code blocks by adding language specifiers like this:

-```
+```bash
 cd backend

Also applies to: 54-56, 61-63, 70-72, 75-77, 80-82, 101-103, 109-117

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

49-49: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


65-65: Fix URL formatting in backticks.

The URLs within backticks contain syntax that may cause rendering issues according to RFC 1738.

To ensure proper rendering, consider one of these alternatives:

-O servidor estará disponível em `http://localhost:3333`.
+O servidor estará disponível em http://localhost:3333.

Or use inline code without backticks:

-O servidor estará disponível em `http://localhost:3333`.
+O servidor estará disponível em: http://localhost:3333

Also applies to: 84-84

🧰 Tools
🪛 LanguageTool

[inconsistency] ~65-~65: O URL contém o caratére inválido segundo RFC 1738. Os caratéres especiais podem ser codificados com % seguido de dois números hexadecimais. Context: ...ev ``` O servidor estará disponível emhttp://localhost:3333`. ### Frontend 1. Navegue até a pasta d...

(URL_VALIDATION)

backend/src/modules/todos/controllers/todo.controller.ts (2)

1-1: Consider removing the eslint-disable comment.

The eslint-disable prettier/prettier comment at the top of the file disables prettier formatting checks for the entire file, which is generally not recommended for maintainability.

If there are specific formatting issues, consider addressing them directly rather than disabling prettier for the entire file.

-/* eslint-disable prettier/prettier */

27-30: Add validation for the ID parameter in update and remove methods.

The id parameter in the update and remove methods is not validated, which could lead to issues if invalid IDs are provided.

Consider using a validation pipe for the ID parameter:

+ import { Controller, Get, Post, Body, Put, Param, Delete, ParseMongoIdPipe } from '@nestjs/common';

  @Put(':id')
- update(@Param('id') id: string, @Body() updateTodoDto: UpdateTodoDto): Promise<Todo> {
+ update(@Param('id', ParseMongoIdPipe) id: string, @Body() updateTodoDto: UpdateTodoDto): Promise<Todo> {
    return this.todoService.update(id, updateTodoDto);
  }

  @Delete(':id')
- remove(@Param('id') id: string | number): Promise<void> {
+ remove(@Param('id', ParseMongoIdPipe) id: string): Promise<void> {
    return this.todoService.remove(id);
  }

This assumes you have a ParseMongoIdPipe available or you can use ParseUUIDPipe if you're using UUIDs.

Also applies to: 32-35

frontend/src/styles/TodoCardStyles.scss (2)

1-1: Consider removing the eslint-disable comment.

The eslint-disable prettier/prettier comment at the top of the file disables prettier formatting checks for the entire file, which is generally not recommended for maintainability.

If there are specific formatting issues, consider addressing them directly rather than disabling prettier for the entire file.

-/* eslint-disable prettier/prettier */

8-8: Consider refactoring the shadow properties into variables.

The box-shadow definitions appear in multiple places but might change with different themes.

Extract the box-shadow values into CSS variables in your theme.scss file to maintain consistency and simplify theme switching:

- box-shadow: var(--card-shadow);
+ box-shadow: var(--card-shadow);

- box-shadow: 0 8px 25px var(--shadow-color);
+ box-shadow: var(--card-shadow-hover);

Then define these variables in your theme.scss file:

:root {
  --card-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
  --card-shadow-hover: 0 8px 25px rgba(0, 0, 0, 0.15);
}

[data-theme="dark"] {
  --card-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
  --card-shadow-hover: 0 8px 25px rgba(0, 0, 0, 0.3);
}

Also applies to: 16-16

PULL_REQUEST.md (1)

139-139: Consider replacing the Anglicism "performance".

In Portuguese, it's preferable to use "desempenho" instead of "performance" which is considered an Anglicism.

-O projeto foi desenvolvido seguindo todas as especificações do desafio, com foco em qualidade de código, usabilidade e performance.
+O projeto foi desenvolvido seguindo todas as especificações do desafio, com foco em qualidade de código, usabilidade e desempenho.
🧰 Tools
🪛 LanguageTool

[locale-violation] ~139-~139: “performance” é um estrangeirismo. É preferível dizer “desempenho”, “atuação”, “apresentação”, “espetáculo” ou “interpretação”.
Context: ...o em qualidade de código, usabilidade e performance. Adicionei vários extras para demonstra...

(PT_BARBARISMS_REPLACE_PERFORMANCE)

backend/src/modules/todos/services/todo.service.ts (3)

1-1: Consider removing or justifying the ESLint/Prettier override.

If there's no specific formatting conflict, it might be beneficial to remove the /* eslint-disable prettier/prettier */ comment to ensure consistent code formatting across the project.


16-25: Handle potential save errors more gracefully.

The create method correctly creates and saves a new Todo document. However, wrapping the save in a try/catch block could provide a more user-friendly error message if the database operation fails.

 async create(createTodoDto: CreateTodoDto): Promise<Todo> {
-  const createdTodo = new this.todoModel(createTodoDto);
-  const savedTodo = await createdTodo.save();
+  let savedTodo;
+  try {
+    const createdTodo = new this.todoModel(createTodoDto);
+    savedTodo = await createdTodo.save();
+  } catch (error) {
+    // You could throw a custom exception or log the error
+    throw new Error('Failed to save the todo item. ' + error.message);
+  }

  const todoObj = savedTodo.toObject();
  todoObj.id = IdFormatter.toNumber(savedTodo._id);

  return todoObj;
}

27-36: Use .lean() for better performance when finding all documents.

Calling .lean() on the Mongoose query will return plain JavaScript objects instead of Mongoose documents, resulting in less overhead. This can provide a performance boost for large datasets.

- const todos = await this.todoModel.find().sort({ isFavorite: -1, createdAt: -1 }).exec();
+ const todos = await this.todoModel
+   .find()
+   .sort({ isFavorite: -1, createdAt: -1 })
+   .lean()
+   .exec();
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 401726f and 4cfb74d.

⛔ Files ignored due to path filters (5)
  • backend/package-lock.json is excluded by !**/package-lock.json
  • frontend/package-lock.json is excluded by !**/package-lock.json
  • frontend/public/favicon.ico is excluded by !**/*.ico
  • frontend/public/logo192.png is excluded by !**/*.png
  • frontend/public/logo512.png is excluded by !**/*.png
📒 Files selected for processing (85)
  • .gitattributes (1 hunks)
  • .github/workflows/ci.yml (1 hunks)
  • Dockerfile.backend (1 hunks)
  • Dockerfile.frontend (1 hunks)
  • PULL_REQUEST.md (1 hunks)
  • README.md (1 hunks)
  • backend/.eslintrc.js (1 hunks)
  • backend/.gitignore (1 hunks)
  • backend/.prettierrc (1 hunks)
  • backend/README.md (1 hunks)
  • backend/nest-cli.json (1 hunks)
  • backend/package.json (1 hunks)
  • backend/src/app.controller.spec.ts (1 hunks)
  • backend/src/app.controller.ts (1 hunks)
  • backend/src/app.module.ts (1 hunks)
  • backend/src/app.service.ts (1 hunks)
  • backend/src/config/corsConfig.ts (1 hunks)
  • backend/src/config/databaseConfig.ts (1 hunks)
  • backend/src/config/id-formatter.ts (1 hunks)
  • backend/src/main.ts (1 hunks)
  • backend/src/modules/todos/controllers/todo.controller.ts (1 hunks)
  • backend/src/modules/todos/dto/create-todo.dto.ts (1 hunks)
  • backend/src/modules/todos/dto/update-todo.dto.ts (1 hunks)
  • backend/src/modules/todos/interfaces/todo.interface.ts (1 hunks)
  • backend/src/modules/todos/module/todo.module.ts (1 hunks)
  • backend/src/modules/todos/schemas/todo.schema.ts (1 hunks)
  • backend/src/modules/todos/services/todo.service.ts (1 hunks)
  • backend/test/app.e2e-spec.ts (1 hunks)
  • backend/test/jest-e2e.json (1 hunks)
  • backend/test/todo.service.spec.ts (1 hunks)
  • backend/tsconfig.build.json (1 hunks)
  • backend/tsconfig.json (1 hunks)
  • docker-compose.yml (1 hunks)
  • er.name (1 hunks)
  • frontend/.eslintrc (1 hunks)
  • frontend/.gitignore (1 hunks)
  • frontend/.prettierrc (1 hunks)
  • frontend/package.json (2 hunks)
  • frontend/src/App.tsx (1 hunks)
  • frontend/src/components/Card/index.tsx (1 hunks)
  • frontend/src/components/DeleteModal/DeleteModalStyles.scss (1 hunks)
  • frontend/src/components/DeleteModal/index.tsx (1 hunks)
  • frontend/src/components/Search/index.tsx (1 hunks)
  • frontend/src/components/SearchBar/index.tsx (1 hunks)
  • frontend/src/components/Todo/index.tsx (1 hunks)
  • frontend/src/components/TodoCard/TodoCard.test.tsx (1 hunks)
  • frontend/src/components/TodoCard/index.tsx (1 hunks)
  • frontend/src/components/TodoFilters/index.tsx (1 hunks)
  • frontend/src/components/TodoForm/index.tsx (1 hunks)
  • frontend/src/components/index.tsx (1 hunks)
  • frontend/src/index.tsx (1 hunks)
  • frontend/src/lib/api.ts (1 hunks)
  • frontend/src/pages/TodoPage.tsx (1 hunks)
  • frontend/src/pages/Vehicles/index.tsx (1 hunks)
  • frontend/src/services/DeleteModalServices.tsx (1 hunks)
  • frontend/src/services/SearchBarServices.tsx (1 hunks)
  • frontend/src/services/TodoCardServices.tsx (1 hunks)
  • frontend/src/services/TodoFormServices.tsx (1 hunks)
  • frontend/src/services/TodoServices.tsx (1 hunks)
  • frontend/src/styles/SearchBarStyles.scss (1 hunks)
  • frontend/src/styles/TodoCardStyles.scss (1 hunks)
  • frontend/src/styles/TodoFiltersStyles.scss (1 hunks)
  • frontend/src/styles/TodoFormStyles.scss (1 hunks)
  • frontend/src/styles/TodoStyles.scss (1 hunks)
  • frontend/src/styles/global.scss (1 hunks)
  • frontend/src/styles/theme.scss (1 hunks)
  • frontend/src/types/CardTypes.tsx (1 hunks)
  • frontend/src/types/DeleteModalTypes.tsx (1 hunks)
  • frontend/src/types/SearchBarTypes.tsx (1 hunks)
  • frontend/src/types/SearchTypes.tsx (1 hunks)
  • frontend/src/types/TodoCardTypes.tsx (1 hunks)
  • frontend/src/types/TodoFiltersTypes.tsx (1 hunks)
  • frontend/src/types/TodoFormTypes.tsx (1 hunks)
  • frontend/src/types/TodoTypes.tsx (1 hunks)
  • frontend/src/utils/DeleteModalUtils.tsx (1 hunks)
  • frontend/src/utils/SearchBarUtils.tsx (1 hunks)
  • frontend/src/utils/TodoCardUtils.tsx (1 hunks)
  • frontend/src/utils/TodoFiltersUtils.tsx (1 hunks)
  • frontend/src/utils/TodoFormUtils.tsx (1 hunks)
  • frontend/src/utils/TodoUtils.tsx (1 hunks)
  • frontend/src/utils/useDeleteModal.tsx (1 hunks)
  • nginx.conf (1 hunks)
  • src/components/Search/index.tsx (0 hunks)
  • src/components/index.tsx (0 hunks)
  • src/lib/api.ts (0 hunks)
💤 Files with no reviewable changes (3)
  • src/components/Search/index.tsx
  • src/components/index.tsx
  • src/lib/api.ts
🧰 Additional context used
🧬 Code Definitions (15)
frontend/src/types/TodoFormTypes.tsx (1)
frontend/src/types/TodoTypes.tsx (1)
  • ITodo (1-8)
backend/src/main.ts (1)
backend/src/config/corsConfig.ts (1)
  • corsConfig (4-9)
frontend/src/components/DeleteModal/index.tsx (1)
frontend/src/types/DeleteModalTypes.tsx (1)
  • DeleteModalProps (1-6)
frontend/src/utils/TodoUtils.tsx (1)
frontend/src/types/TodoTypes.tsx (1)
  • ITodo (1-8)
frontend/src/types/TodoCardTypes.tsx (1)
frontend/src/types/TodoTypes.tsx (1)
  • ITodo (1-8)
backend/src/modules/todos/module/todo.module.ts (2)
backend/src/config/databaseConfig.ts (1)
  • databaseConfig (5-5)
backend/src/modules/todos/schemas/todo.schema.ts (1)
  • TodoSchema (25-25)
frontend/src/services/TodoCardServices.tsx (2)
frontend/src/types/TodoTypes.tsx (1)
  • ITodo (1-8)
frontend/src/lib/api.ts (2)
  • put (21-24)
  • del (26-29)
frontend/src/services/DeleteModalServices.tsx (1)
frontend/src/lib/api.ts (1)
  • del (26-29)
frontend/src/services/TodoFormServices.tsx (2)
frontend/src/types/TodoTypes.tsx (1)
  • ITodo (1-8)
frontend/src/lib/api.ts (2)
  • post (16-19)
  • put (21-24)
frontend/src/pages/Vehicles/index.tsx (2)
frontend/src/types/Vehicle.ts (1)
  • IVehicle (1-11)
frontend/src/lib/api.ts (1)
  • get (11-14)
frontend/src/components/Todo/index.tsx (3)
frontend/src/services/TodoServices.tsx (2)
  • useTodos (9-16)
  • invalidateTodosCache (18-20)
frontend/src/types/TodoTypes.tsx (1)
  • ITodo (1-8)
frontend/src/components/index.tsx (4)
  • SearchBar (11-11)
  • TodoFilters (11-11)
  • TodoCard (11-11)
  • TodoForm (11-11)
frontend/src/utils/TodoCardUtils.tsx (1)
frontend/src/types/TodoTypes.tsx (1)
  • ITodo (1-8)
frontend/src/components/TodoForm/index.tsx (2)
frontend/src/types/TodoFormTypes.tsx (1)
  • TodoFormProps (3-7)
frontend/src/utils/TodoFormUtils.tsx (1)
  • useTodoForm (15-57)
backend/src/modules/todos/controllers/todo.controller.ts (2)
backend/src/modules/todos/dto/create-todo.dto.ts (1)
  • CreateTodoDto (4-20)
backend/src/modules/todos/dto/update-todo.dto.ts (1)
  • UpdateTodoDto (4-20)
frontend/src/utils/TodoFormUtils.tsx (1)
frontend/src/types/TodoTypes.tsx (1)
  • ITodo (1-8)
🪛 YAMLlint (1.35.1)
docker-compose.yml

[error] 46-46: no new line character at the end of file

(new-line-at-end-of-file)


[error] 46-46: trailing spaces

(trailing-spaces)

.github/workflows/ci.yml

[error] 15-15: trailing spaces

(trailing-spaces)


[error] 20-20: trailing spaces

(trailing-spaces)


[error] 25-25: trailing spaces

(trailing-spaces)


[error] 30-30: trailing spaces

(trailing-spaces)


[error] 35-35: trailing spaces

(trailing-spaces)


[error] 46-46: trailing spaces

(trailing-spaces)


[error] 51-51: trailing spaces

(trailing-spaces)


[error] 56-56: trailing spaces

(trailing-spaces)


[error] 61-61: trailing spaces

(trailing-spaces)


[error] 66-66: trailing spaces

(trailing-spaces)


[error] 79-79: trailing spaces

(trailing-spaces)


[error] 82-82: trailing spaces

(trailing-spaces)


[error] 90-90: trailing spaces

(trailing-spaces)


[error] 97-97: no new line character at the end of file

(new-line-at-end-of-file)


[error] 97-97: trailing spaces

(trailing-spaces)

🪛 Gitleaks (8.21.2)
backend/README.md

5-5: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 LanguageTool
backend/README.md

[style] ~76-~76: The expression “come in handy” is rather colloquial. Consider replacing it to add a more formal tone to your writing.
Context: ...ces Check out a few resources that may come in handy when working with NestJS: - Visit the ...

(COME_IN_HANDY)


[uncategorized] ~89-~89: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...). ## Support Nest is an MIT-licensed open source project. It can grow thanks to the spon...

(EN_COMPOUND_ADJECTIVE_INTERNAL)


[style] ~89-~89: Consider using a more formal and expressive alternative to ‘amazing’.
Context: ...anks to the sponsors and support by the amazing backers. If you'd like to join them, pl...

(AWESOME)

README.md

[inconsistency] ~65-~65: O URL contém o caratére inválido segundo RFC 1738. Os caratéres especiais podem ser codificados com % seguido de dois números hexadecimais. Context: ...ev ``` O servidor estará disponível emhttp://localhost:3333`. ### Frontend 1. Navegue até a pasta d...

(URL_VALIDATION)


[inconsistency] ~84-~84: O URL contém o caratére inválido segundo RFC 1738. Os caratéres especiais podem ser codificados com % seguido de dois números hexadecimais. Context: ...t ``` A aplicação estará disponível emhttp://localhost:3000`. ## Extras implementados ### 1. Tipage...

(URL_VALIDATION)

PULL_REQUEST.md

[locale-violation] ~139-~139: “performance” é um estrangeirismo. É preferível dizer “desempenho”, “atuação”, “apresentação”, “espetáculo” ou “interpretação”.
Context: ...o em qualidade de código, usabilidade e performance. Adicionei vários extras para demonstra...

(PT_BARBARISMS_REPLACE_PERFORMANCE)

🪛 markdownlint-cli2 (0.17.2)
backend/README.md

5-5: Link and image reference definitions should be needed
Unused link or image reference definition: "circleci-image"

(MD053, link-image-reference-definitions)


6-6: Link and image reference definitions should be needed
Unused link or image reference definition: "circleci-url"

(MD053, link-image-reference-definitions)


32-32: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)


68-68: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)


69-69: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)

README.md

49-49: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


54-54: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


61-61: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


70-70: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


75-75: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


80-80: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


101-101: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


109-109: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


125-125: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


139-139: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

🪛 Biome (1.9.4)
backend/src/config/id-formatter.ts

[error] 4-38: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

🪛 actionlint (1.7.4)
.github/workflows/ci.yml

14-14: the runner of "actions/checkout@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


17-17: the runner of "actions/setup-node@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


45-45: the runner of "actions/checkout@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


48-48: the runner of "actions/setup-node@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


78-78: the runner of "actions/checkout@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


81-81: the runner of "docker/setup-buildx-action@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


84-84: the runner of "docker/build-push-action@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


92-92: the runner of "docker/build-push-action@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🔇 Additional comments (74)
backend/tsconfig.build.json (1)

1-4: Configuration File Setup Verified

The new tsconfig.build.json file correctly extends the base configuration from tsconfig.json and excludes folders and file patterns (such as node_modules, test, dist, and **/*spec.ts) that are not needed for the build. This setup will help streamline the build process by omitting extraneous files.

backend/nest-cli.json (1)

1-9: Configuration File Valid and Consistent

The JSON configuration adheres to the NestJS CLI schema and correctly specifies the essential fields:

  • The $schema property properly points to "https://json.schemastore.org/nest-cli".
  • The collection is set to "@nestjs/schematics", maintaining consistency with common NestJS practices.
  • The sourceRoot being "src" is standard for project structure.
  • The compilerOptions with "deleteOutDir": true is useful for ensuring a clean build each time.

Overall, the file is well-structured and follows best practices for a NestJS CLI configuration.

frontend/.gitignore (6)

1-2: Informative Header Comment

The header clearly references GitHub’s documentation on ignoring files, which is helpful for quick reference.


3-7: Dependency Ignore Patterns

The dependencies block correctly ignores common directories and files—such as /node_modules, /.pnp, and .pnp.js—that should not be tracked in version control. This helps maintain a clean repository.


8-10: Testing Artifacts Exclusion

The test section effectively excludes the /coverage directory generated during testing, ensuring these artifacts do not clutter the repository.


11-13: Production Build Artifacts

The production block accurately ignores the /build directory, which is standard for build outputs in many frontend projects.


14-20: Miscellaneous File Exclusions

The miscellaneous section reliably covers system-generated files (like .DS_Store) and various environment configuration files. This is important to prevent sensitive configurations from being committed.


21-23: Log Files Exclusion

The patterns for log files (npm-debug.log*, yarn-debug.log*, and yarn-error.log*) are well chosen to keep debugging logs out of version control.

backend/.prettierrc (1)

1-11: Well-configured Prettier setup that follows best practices

The Prettier configuration follows modern JavaScript/TypeScript best practices with sensible defaults. The settings like single quotes, trailing commas, 2-space indentation, and 100 character line width provide a good balance between readability and consistency.

backend/.gitignore (1)

1-56: Comprehensive .gitignore with well-organized sections

This .gitignore file is thorough and well-organized, covering all standard files and directories that should be excluded from version control in a Node.js/NestJS project.

The file correctly handles:

  • Build outputs and dependencies
  • Logs and debug files
  • Testing artifacts
  • IDE-specific files (while allowing useful VS Code settings)
  • Environment files for security
  • Temporary and runtime files
backend/.eslintrc.js (1)

1-33: Well-balanced ESLint configuration for TypeScript development

The ESLint configuration strikes a good balance between enforcing best practices and not being overly restrictive, with appropriate integration of Prettier.

Notable strengths:

  • Good TypeScript integration with sensible rule customizations
  • Balanced approach to linting severity (warnings vs errors)
  • Proper console usage restrictions with allowances for warnings/errors
  • Strong code quality rules like no-duplicate-imports and prefer-const

This configuration supports the project's goal of maintaining high code quality.

backend/README.md (1)

5-6:

❓ Verification inconclusive

Security & Unused Reference Definitions: Exposed Token & Unused Link References

The image reference on line 5 includes a token (token=abc123def456). If this token were real or grants any privileges, it may expose sensitive information. Consider removing or securing it (e.g., by using environment variables or a configuration file). Also, the link reference on line 6 ([circleci-url]) isn’t apparently used in the document. Either incorporate it into the README where needed or remove it to clean up the file.


Attention: Exposed Token & Unused Link Reference in README

  • The CircleCI image reference (line 5) embeds a token (token=abc123def456). Verify whether this token is live or merely a placeholder. If it’s active—or could be accidentally activated in a real scenario—please remove it or secure it using environment variables/configuration files.
  • The [circleci-url] definition (line 6) isn’t referenced anywhere in the document. If it’s not used, consider removing it to avoid confusion; otherwise, integrate it appropriately in the README.
🧰 Tools
🪛 Gitleaks (8.21.2)

5-5: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 markdownlint-cli2 (0.17.2)

5-5: Link and image reference definitions should be needed
Unused link or image reference definition: "circleci-image"

(MD053, link-image-reference-definitions)


6-6: Link and image reference definitions should be needed
Unused link or image reference definition: "circleci-url"

(MD053, link-image-reference-definitions)

frontend/src/utils/SearchBarUtils.tsx (1)

1-4: Structural Placeholder: Maintaining Project Consistency

This file serves as a structural placeholder for potential future utilities related to the SearchBar component. The comments clearly explain its purpose. If no utilities are needed at present, this minimal export is acceptable.

frontend/src/services/SearchBarServices.tsx (1)

1-5: Structural Placeholder: Consistent Service Structure

The file is correctly implemented as a placeholder for SearchBar-related services, explaining that no direct API calls are needed. This maintains the project’s modular structure.

frontend/src/pages/TodoPage.tsx (1)

1-8: TodoPage Component: Clean and Focused Implementation

The new TodoPage component (lines 1–8) is straightforward and correctly imports and renders the Todo component. The use of React.FC is acceptable here. In future iterations, you might consider enhancing this component with error boundaries or loading states if the todo list operations become more complex.

.gitattributes (1)

1-3: Line Ending Normalization: Correct Configuration

The new .gitattributes file properly enforces LF normalization across text files, which will help maintain consistency across different operating systems. The configuration is correct.

frontend/src/types/CardTypes.tsx (1)

1-6: Well-structured type definition!

The ICardProps interface is properly defined with appropriate types for a React card component. Using ReactNode for the children prop follows React best practices for allowing any valid JSX content.

frontend/src/App.tsx (1)

2-9: Clean and straightforward App component.

The App component is well-structured and follows React best practices by using a functional component approach. It serves as a clear entry point to the application by rendering the main TodoPage component.

frontend/src/components/index.tsx (1)

2-11: Good use of barrel file pattern for component exports.

This implementation provides a clean and convenient way to import multiple components from a single location, which improves code organization and readability.

frontend/src/types/SearchBarTypes.tsx (1)

1-5: Ensure consistency with ISearchProps interface

I noticed inconsistencies between this SearchBarProps interface and the ISearchProps interface in SearchTypes.tsx. They seem to serve similar purposes but have different signatures for the onChange function. Consider consolidating these interfaces or ensuring they're used for different, well-defined purposes.

Are both interfaces needed in your application, or could you consolidate them to maintain consistency? If they serve different purposes, make sure your component implementations align with these different type definitions.

backend/src/app.module.ts (1)

7-11: The module structure looks good

The NestJS module is well-structured with proper imports, controllers, and providers. Good job following the NestJS architectural patterns.

backend/src/app.service.ts (1)

1-8: Simple service implementation looks good

This is a standard NestJS service with a basic "Hello World" method. The implementation follows the framework's conventions with proper decorator usage.

Dockerfile.backend (1)

5-7: Use separate steps for package.json and dependency installation

This approach properly leverages Docker's layer caching by copying only package files first and installing dependencies before copying the rest of the code.

frontend/src/styles/theme.scss (1)

3-24: Good implementation of dark theme variables

The dark theme variables are well-organized and comprehensive, covering all necessary UI elements with consistent naming patterns.

frontend/src/types/TodoFormTypes.tsx (1)

1-7: Well-defined interface with appropriate type constraints

The TodoFormProps interface is well designed:

  • The todo property is correctly marked as optional for creating new todos
  • The onSave function smartly omits id and createdAt from the saved todo since these are typically managed server-side
  • The onCancel function has a clear return type signature

This accurately models the component's requirements.

backend/src/app.controller.spec.ts (1)

1-22: Well-structured unit test for AppController

This is a clean and concise unit test for the AppController. The test properly sets up the testing module with the necessary controller and service dependencies, and verifies that the controller's getHello() method returns the expected "Hello World!" string.

frontend/src/types/TodoFiltersTypes.tsx (1)

1-6: Good TypeScript interface definition

The TodoFiltersProps interface is well-defined with clear type annotations for filter-related properties. It properly includes both state values (selectedColor, showOnlyFavorites) and their corresponding handler functions (onColorSelect, onFavoriteToggle) with appropriate function signatures.

frontend/.prettierrc (1)

1-13: Configuration looks good with sensible defaults

The Prettier configuration has good defaults that align with modern JavaScript/TypeScript practices. The choices for semicolons, single quotes, tab width of 2, and other formatting options will help maintain consistent code style throughout the project.

frontend/src/utils/TodoUtils.tsx (2)

1-3: Clean imports with appropriate naming conventions

The imports are well-organized, separating types from services with clear naming.


4-10: Well-implemented sorting utility with immutability

Good implementation of the sortTodosByFavorite function. The use of spread operator to create a new array preserves immutability, which is important for React applications. The sorting logic is clear and correctly prioritizes favorites.

backend/src/modules/todos/dto/create-todo.dto.ts (1)

4-20: Well-structured DTO with proper validation

The DTO uses appropriate class-validator decorators to enforce validation rules for the todo entity. The properties and types are well-defined with good validation constraints.

backend/src/app.controller.ts (1)

1-12: Well-structured controller implementation

The AppController follows best practices with proper dependency injection and clear method structure. The controller is focused and concise.

backend/test/jest-e2e.json (1)

1-9: Appropriate Jest E2E testing configuration

The Jest configuration is properly set up for E2E testing with the correct file extensions, test environment, and transformation settings.

backend/src/modules/todos/module/todo.module.ts (2)

9-16: Well-structured module with proper component registration

The module follows NestJS best practices with appropriate imports, controller, and provider registration. The structure is clean and organized.


7-7:

❓ Verification inconclusive

Verify database configuration implementation

The imported databaseConfig appears to be an empty object based on the code snippet provided. Ensure that this configuration is properly implemented with any necessary MongoDB connection options.


🏁 Script executed:

#!/bin/bash
# Check the implementation of databaseConfig
cat backend/src/config/databaseConfig.ts

Length of output: 254


Database Configuration Verification

The file backend/src/config/databaseConfig.ts intentionally exports an empty object (with the comment “Objeto vazio para usar apenas as configurações padrão”) so that Mongoose’s default configurations are used. If this is the desired behavior, no changes are required. However, if you plan to override or enhance MongoDB connection options (for example, using custom values for useNewUrlParser, useUnifiedTopology, or connection timeouts), please update this file accordingly and add a clarifying comment for future maintainers.

frontend/src/types/TodoCardTypes.tsx (1)

1-8: Well-defined TypeScript interface with clear callback signatures.

The TodoCardProps interface correctly defines the structure for the TodoCard component props, with proper typing for the todo object and callback functions. This approach ensures type safety throughout the application and makes component interactions explicit.

backend/src/modules/todos/schemas/todo.schema.ts (1)

7-23: Well-structured Todo schema with proper field definitions.

The schema is well-designed with appropriate field types, required constraints, and default values. The timestamp configuration is correctly set to track creation time only.

Dockerfile.frontend (1)

3-11: Good use of Docker caching for dependencies.

The Dockerfile correctly follows best practices by copying package files first, installing dependencies, then copying the rest of the code. This approach optimizes build times by leveraging Docker's layer caching.

frontend/package.json (3)

6-6: Good choice of modern dependencies for frontend functionality.

The addition of React Query (@tanstack/react-query) for data fetching, Axios for HTTP requests, and React Icons for UI elements are appropriate choices for a modern React application.

Also applies to: 14-14, 18-18


56-59: Good addition of code quality tools.

Adding Prettier and ESLint integration helps maintain code quality and consistency across the project.


15-15:

✅ Verification successful

Consider replacing deprecated node-sass.

The node-sass package is deprecated and may cause compatibility issues in the future. Consider replacing it with the maintained sass package.

-    "node-sass": "^7.0.1",
+    "sass": "^1.71.1",

🌐 Web query:

Is node-sass deprecated? What is the recommended alternative?

💡 Result:

Node Sass has been deprecated as of July 2024, with its npm package marked as deprecated and GitHub repository archived. The LibSass engine it relied on also remains deprecated[3][5]. This decision followed years of declining maintenance and an inability to keep up with modern CSS and Sass features[3][5].

The recommended alternative is Dart Sass, the primary Sass implementation actively maintained by the Sass team. Key advantages include:

  • Full support for modern Sass/CSS features like calc() and modules[1][3]
  • No native bindings or compilation dependencies[1][8]
  • Active development with regular updates[3][8]

Migration steps from Node Sass to Dart Sass:

  1. Remove Node Sass dependencies:
    npm uninstall node-sass
  2. Install Dart Sass:
    npm install --save-dev sass
  3. Update build scripts:
    • Change node-sass to sass in package.json[1]
    • Replace --output-style compressed with --style=compressed[1]
    • Add --load-path=node_modules/ for module resolution[1]

Performance comparisons show Dart Sass (native Dart VM) compiles faster than both Node Sass and its JavaScript implementation, though the JS version remains slower than LibSass in some scenarios[8]. For most projects, the maintainability and feature advantages outweigh minor performance tradeoffs[3][8].

Citations:


Update Dependency to Dart Sass
The current dependency on node-sass (version ^7.0.1) is deprecated. It is recommended to replace it with Dart Sass via the sass package. Please update your frontend/package.json accordingly:

-    "node-sass": "^7.0.1",
+    "sass": "^1.71.1",

Additionally, ensure that any associated build scripts or configuration files that reference node-sass are updated to use sass. This change will help avoid future compatibility issues and take advantage of the enhanced features provided by Dart Sass.

frontend/src/components/DeleteModal/index.tsx (1)

6-8: Good use of conditional rendering for the modal.

The component correctly uses conditional rendering with an early return when isOpen is false, which is an efficient approach.

frontend/.eslintrc (1)

1-38: Well-structured ESLint configuration for TypeScript and React

The ESLint configuration is comprehensive and follows modern React and TypeScript development best practices. It uses appropriate extensions, plugins, and rules while maintaining a good balance between strictness and practicality (using warnings instead of errors for some rules).

I particularly like:

  • Disabling React import requirement (appropriate for React 17+)
  • Proper enforcement of React hooks rules
  • Ignoring unused variables that start with underscore (good convention)
  • Disabling prop-types (redundant with TypeScript)
frontend/src/pages/Vehicles/index.tsx (2)

11-11: Good addition of loading state

Adding a loading state variable is good practice for handling asynchronous operations.


15-22: Improved error handling with try-catch-finally

The implementation of proper error handling is a good improvement. The try-catch-finally pattern ensures:

  • Errors are properly caught and logged
  • Loading state is correctly updated regardless of success or failure
frontend/src/styles/global.scss (2)

12-14: Good use of CSS variables for theming

Using CSS variables for theming is an excellent choice as it enables easy theme switching (light/dark modes) without duplicate style definitions.


31-59: Well-implemented animations enhance UX

The defined animations and their application to specific components create a polished user experience. The timing and easing functions are appropriate for subtle motion that doesn't distract from the content.

nginx.conf (1)

1-20: Good Nginx configuration for a React SPA with API proxy

The configuration is well-structured for a single-page application with separate frontend and backend services:

  • Correctly set up to serve static files and handle client-side routing with the fallback to index.html
  • Properly configured proxy for API requests with appropriate headers for WebSocket support
  • Good separation between frontend and backend concerns
frontend/src/utils/TodoFiltersUtils.tsx (3)

3-11: Well-structured color palette with clear comments!

The color constants are well-defined with helpful comments indicating color names. This makes it easy to understand the available palette for todo items.


13-16: Clean and effective filter implementation.

The filterTodosByColor function correctly handles both the null case and filtering by specific color. The implementation is concise and follows functional programming best practices.


18-21: Good implementation of the favorites filter.

The filterTodosByFavorite function is well-implemented, efficiently handling the conditional filtering of todos.

frontend/src/components/TodoCard/TodoCard.test.tsx (6)

6-13: Well-structured mock data for testing.

The mock todo object contains all necessary properties with appropriate test values, providing a good foundation for the test cases.


19-22: Good test isolation practice.

Using beforeEach with jest.clearAllMocks() ensures that each test starts with a clean slate, preventing interference between tests.


24-36: Comprehensive rendering test.

This test effectively verifies that the component renders the expected content, ensuring the basic display functionality works correctly.


38-52: Well-implemented interaction test for favorites.

The test correctly verifies that clicking the favorite button triggers the callback with the right parameters. Using getByLabelText is a good accessibility practice.


54-68: Effective edit functionality test.

This test properly verifies that the edit button works correctly and passes the right data to the callback function.


70-86: Good modal interaction testing.

The test effectively verifies that clicking the delete button opens the confirmation modal with the correct content. The expectations are clear and meaningful.

frontend/src/components/DeleteModal/DeleteModalStyles.scss (2)

1-12: Well-implemented modal overlay.

The overlay covers the entire viewport with a semi-transparent background and centers its content, providing a good user experience when displaying the modal.


14-31: Responsive modal content with good styling.

The modal content has appropriate styling with good spacing, colors, and a responsive width that works well on different screen sizes.

backend/src/config/id-formatter.ts (1)

28-30: Simple and effective toString method.

This method correctly converts an ObjectId to its string representation.

frontend/src/index.tsx (1)

4-6: Good implementation of React Query.

The integration of React Query with a QueryClientProvider is well done. This will provide efficient data fetching, caching, and state management for your Todo application.

Also applies to: 9-19

frontend/src/components/TodoForm/index.tsx (1)

6-78: Well-structured form component.

The TodoForm component is well-organized and makes good use of custom hooks for state management. Props are properly typed using the TodoFormProps interface, and the form includes all necessary fields with appropriate validation.

frontend/src/utils/TodoFormUtils.tsx (1)

15-57: Well-structured custom hook.

The useTodoForm hook is well-implemented with clear state management and appropriate side effects for initializing from an existing todo. The form validation is simple but effective for the requirements.

frontend/src/styles/TodoFiltersStyles.scss (2)

4-101: Well-structured filter component with good UX considerations

The filter component styling is well-organized with proper nesting, variable usage, and interactive elements. The hover and selection states provide good visual feedback to users.


59-100:

✅ Verification successful

Ensure checkbox has an accessible label

The current implementation styles a checkbox and its label, but make sure they're properly associated in the HTML with a for attribute that matches the checkbox's id.


🏁 Script executed:

#!/bin/bash
# Search for the favorite filter implementation to verify proper label association
rg -A 10 "favorite-filter" --type tsx

Length of output: 65


I'll generate a new verification script that searches TSX files by explicitly specifying the file pattern rather than the file type. This should help us locate the code where the checkbox and its label are rendered.

Please run this script so we can verify if the checkbox and label are properly associated (i.e., the input's id matches the label’s for attribute).


🏁 Script executed:

#!/bin/bash
# Search for the favorite filter implementation in TSX files to verify proper label association
rg -A 10 "favorite-filter" -g "*.tsx"

Length of output: 1016


Accessible Label Verified: No changes required

The <input> and <label> elements in frontend/src/components/TodoFilters/index.tsx are properly associated using the id="show-favorites" on the input and htmlFor="show-favorites" on the label.

  • File verified: frontend/src/components/TodoFilters/index.tsx
  • Verification result: Proper accessible label is already implemented.
frontend/src/styles/TodoStyles.scss (1)

4-143: Well-structured and visually appealing styling

The TodoStyles provide a cohesive design with good visual hierarchy, animations, and consistent use of CSS variables for theming. The BEM-like naming convention makes the code easy to maintain.

README.md (1)

1-155: LGTM! Comprehensive and well-structured README.

The README provides clear, detailed information about the project structure, technologies, functionalities, and setup instructions. It's well-organized with proper headings and lists, making it easy to follow.

🧰 Tools
🪛 LanguageTool

[inconsistency] ~65-~65: O URL contém o caratére inválido segundo RFC 1738. Os caratéres especiais podem ser codificados com % seguido de dois números hexadecimais. Context: ...ev ``` O servidor estará disponível emhttp://localhost:3333`. ### Frontend 1. Navegue até a pasta d...

(URL_VALIDATION)


[inconsistency] ~84-~84: O URL contém o caratére inválido segundo RFC 1738. Os caratéres especiais podem ser codificados com % seguido de dois números hexadecimais. Context: ...t ``` A aplicação estará disponível emhttp://localhost:3000`. ## Extras implementados ### 1. Tipage...

(URL_VALIDATION)

🪛 markdownlint-cli2 (0.17.2)

49-49: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


54-54: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


61-61: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


70-70: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


75-75: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


80-80: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


101-101: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


109-109: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


125-125: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


139-139: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

backend/src/modules/todos/controllers/todo.controller.ts (1)

2-36: LGTM! Well-structured controller following RESTful principles.

The controller is well organized with clear method signatures and appropriate HTTP verb decorators. It follows the standard RESTful API design pattern with proper endpoint definitions.

frontend/src/styles/TodoCardStyles.scss (2)

4-111: Great job with the detailed, well-structured SCSS.

The styles for the todo card are comprehensive, with careful attention to hover states, animations, and responsive design. The use of CSS variables enables theming support, and the BEM-like naming convention makes the code easy to understand and maintain.


6-9: Excellent use of transitions and hover effects.

The subtle animations and hover effects (translation, shadow changes, scaling) create a polished and interactive UI. The use of CSS variables for colors supports the theme switching functionality mentioned in the PR summary.

Also applies to: 14-17, 19-27, 50-53, 95-99, 101-107

PULL_REQUEST.md (3)

1-148: Excellent PR documentation with comprehensive details!

This is an exceptionally well-documented pull request that clearly outlines all the implementations, technologies used, and extra features added. The structured format with sections for frontend, backend, and extras makes it easy to understand the scope of changes.

🧰 Tools
🪛 LanguageTool

[locale-violation] ~139-~139: “performance” é um estrangeirismo. É preferível dizer “desempenho”, “atuação”, “apresentação”, “espetáculo” ou “interpretação”.
Context: ...o em qualidade de código, usabilidade e performance. Adicionei vários extras para demonstra...

(PT_BARBARISMS_REPLACE_PERFORMANCE)


51-85: Impressive list of extra implementations.

The additional implementations beyond the core requirements demonstrate a high level of commitment and technical proficiency. The inclusion of TypeScript interfaces, ESLint/Prettier configurations, Docker setup, tests, and CI/CD pipeline is particularly noteworthy.


86-110: Great attention to UI/UX details.

The detailed descriptions of UI components and interactions show careful consideration for user experience. Features like animations, color selectors, and theme toggle with smooth transitions enhance the application's usability.

backend/src/modules/todos/services/todo.service.ts (1)

10-15: Dependency injection setup looks good.

Using @Injectable() and injecting the todoModel through the constructor appropriately follows NestJS conventions.

Comment on lines +4 to +5
// Objeto vazio para usar apenas as configurações padrão
export const databaseConfig: MongooseModuleOptions = {};
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Consider adding more explicit configuration or documentation.

The empty configuration object is valid if you're relying on defaults, but it might make it harder to understand the actual connection details being used. Consider:

  1. Adding more explicit configuration to improve clarity
  2. Including detailed comments about what default values are being used
  3. Using English for comments to maintain consistency with code and identifiers
- // Objeto vazio para usar apenas as configurações padrão
+ // Empty object to use default configuration only
+ // Default connection: mongodb://127.0.0.1:27017/[project-name]
export const databaseConfig: MongooseModuleOptions = {};

🏁 Script executed:

#!/bin/bash
# Check where this configuration is used to understand the context better
rg -A 5 "databaseConfig" --type typescript

Length of output: 77


Action Needed: Enhance Clarity in databaseConfig Usage

Please update the empty configuration object to include explicit documentation clarifying that default connection parameters are being relied upon. In particular:

  • Document the assumed default values (e.g., default MongoDB URI such as mongodb://127.0.0.1:27017/[project-name]).
  • Use English in comments to maintain consistency with the codebase.
  • Verify manually that the usage of databaseConfig across the repository aligns with these documented defaults.

Here's the proposed diff:

- // Objeto vazio para usar apenas as configurações padrão
+ // Empty object to use default configuration only
+ // Default connection: mongodb://127.0.0.1:27017/[project-name]
export const databaseConfig: MongooseModuleOptions = {};

Please run the above script to check all occurrences of databaseConfig and confirm that all usages assume the same defaults. Manual verification of this context will help ensure that the documentation accurately reflects the behavior across the application.


---

🏁 Script executed:

```shell

#!/bin/bash
# Searching for occurrences of "databaseConfig" in the codebase using the recognized file type "ts"
rg -A 5 "databaseConfig" --type ts

Length of output: 1049


Clarify Default Database Configuration

The empty databaseConfig object is valid if relying on Mongoose's default options. However, its usage in backend/src/modules/todos/module/todo.module.ts (where the connection URL is explicitly provided as mongodb://localhost:27017/todolist_db) may leave future readers unclear about which defaults are applied. To improve understandability and consistency, please consider updating the comment as follows:

- // Objeto vazio para usar apenas as configurações padrão
+ // Empty object to use default configuration only.
+ // Default connection is set in MongooseModule.forRoot as: mongodb://localhost:27017/todolist_db
export const databaseConfig: MongooseModuleOptions = {};

Please verify that this documentation aligns with how defaults are expected to work across the codebase.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Objeto vazio para usar apenas as configurações padrão
export const databaseConfig: MongooseModuleOptions = {};
// Empty object to use default configuration only.
// Default connection is set in MongooseModule.forRoot as: mongodb://localhost:27017/todolist_db
export const databaseConfig: MongooseModuleOptions = {};

Comment on lines +4 to +6
export const deleteTodo = async (id: number): Promise<void> => {
return del(`/todos/${id}`);
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling to improve robustness.

The current implementation doesn't handle potential errors that might occur during the delete operation. Consider adding try/catch to properly handle errors.

export const deleteTodo = async (id: number): Promise<void> => {
-  return del(`/todos/${id}`);
+  try {
+    return await del(`/todos/${id}`);
+  } catch (error) {
+    console.error('Error deleting todo:', error);
+    throw error;
+  }
}; 
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const deleteTodo = async (id: number): Promise<void> => {
return del(`/todos/${id}`);
};
export const deleteTodo = async (id: number): Promise<void> => {
try {
return await del(`/todos/${id}`);
} catch (error) {
console.error('Error deleting todo:', error);
throw error;
}
};

Comment on lines +3 to +7
const Search = (props: ISearchProps) => {
return (
<input type="text" placeholder={props.placeholder} value={props.value} />
);
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Missing onChange handler for the input element.

The Search component is rendering a controlled input (with a value prop) but doesn't include the required onChange handler. This will make the input read-only and prevent users from typing in it. According to the ISearchProps interface mentioned in the summary, there should be an onChange prop that needs to be used here.

const Search = (props: ISearchProps) => {
  return (
-    <input type="text" placeholder={props.placeholder} value={props.value} />
+    <input 
+      type="text" 
+      placeholder={props.placeholder} 
+      value={props.value} 
+      onChange={props.onChange} 
+    />
  );
};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const Search = (props: ISearchProps) => {
return (
<input type="text" placeholder={props.placeholder} value={props.value} />
);
};
const Search = (props: ISearchProps) => {
return (
<input
type="text"
placeholder={props.placeholder}
value={props.value}
onChange={props.onChange}
/>
);
};

Comment on lines +4 to +9
export const corsConfig: CorsOptions = {
origin: 'http://localhost:3000',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
};
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Use environment variables for CORS configuration.

The origin is currently hardcoded to 'http://localhost:3000', which will only work in development. For a more flexible solution that works across different environments (development, staging, production), consider using environment variables.

export const corsConfig: CorsOptions = {
-  origin: 'http://localhost:3000',
+  origin: process.env.ALLOWED_ORIGINS?.split(',') || 'http://localhost:3000',
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true,
}; 

This change allows you to configure multiple allowed origins through an environment variable (comma-separated) while maintaining localhost as a fallback for development.

Make sure to update your environment configuration and documentation to include the new ALLOWED_ORIGINS variable.


Action Required: Update CORS Configuration to Use Environment Variables

The current configuration in backend/src/config/corsConfig.ts uses a hardcoded origin ('http://localhost:3000'), which only works for development. To support multiple environments (development, staging, production), update this configuration to read from an environment variable. For example, consider the following change:

export const corsConfig: CorsOptions = {
-  origin: 'http://localhost:3000',
+  origin: process.env.ALLOWED_ORIGINS?.split(',') || 'http://localhost:3000',
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true,
};

Please update your environment configuration and documentation to include the new ALLOWED_ORIGINS variable.


🏁 Script executed:

#!/bin/bash
# Verify that the current CORS configuration in backend/src/config/corsConfig.ts contains the hardcoded origin.
grep -R "origin:" backend/src/config/corsConfig.ts

Length of output: 207


Action Required: Update CORS Configuration to Use Environment Variables

  • In backend/src/config/corsConfig.ts (lines 4-9), the origin is hardcoded as 'http://localhost:3000', which limits its use to a development environment.

  • To support multiple environments, update the configuration to source the allowed origins from an environment variable. This enables flexibility for development, staging, and production settings.

  • Recommended Diff:

    export const corsConfig: CorsOptions = {
    -  origin: 'http://localhost:3000',
    +  origin: process.env.ALLOWED_ORIGINS?.split(',') || 'http://localhost:3000',
      methods: ['GET', 'POST', 'PUT', 'DELETE'],
      allowedHeaders: ['Content-Type', 'Authorization'],
      credentials: true,
    };
  • Next Steps:
    Ensure your environment configuration (and any relevant documentation) includes the new ALLOWED_ORIGINS variable to properly manage allowed origins across different deployment stages.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const corsConfig: CorsOptions = {
origin: 'http://localhost:3000',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
};
export const corsConfig: CorsOptions = {
origin: process.env.ALLOWED_ORIGINS?.split(',') || 'http://localhost:3000',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
};

Comment on lines +1 to +5
export interface ISearchProps {
placeholder: string;
value: string;
onChange: () => void;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Fix the onChange handler type signature

The onChange function doesn't accept any parameters, which is unusual for a search component. Typically, an onChange handler in React should receive either an event parameter or at least the new input value to update state.

export interface ISearchProps {
  placeholder: string;
  value: string;
-  onChange: () => void;
+  onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
} 

Alternatively, if you prefer passing just the value:

export interface ISearchProps {
  placeholder: string;
  value: string;
-  onChange: () => void;
+  onChange: (value: string) => void;
} 
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export interface ISearchProps {
placeholder: string;
value: string;
onChange: () => void;
}
export interface ISearchProps {
placeholder: string;
value: string;
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
}
Suggested change
export interface ISearchProps {
placeholder: string;
value: string;
onChange: () => void;
}
export interface ISearchProps {
placeholder: string;
value: string;
onChange: (value: string) => void;
}

}

@Delete(':id')
remove(@Param('id') id: string | number): Promise<void> {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Inconsistent parameter type in the remove method.

The id parameter in the remove method accepts string | number while other methods only accept string. This is inconsistent with the rest of the controller and could lead to type conversion issues.

For consistency, use the same type for the id parameter across all methods:

-  remove(@Param('id') id: string | number): Promise<void> {
+  remove(@Param('id') id: string): Promise<void> {
     return this.todoService.remove(id);
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
remove(@Param('id') id: string | number): Promise<void> {
remove(@Param('id') id: string): Promise<void> {
return this.todoService.remove(id);
}

Comment on lines +22 to +25
@Get(':id')
findOne(@Param('id') id: string): Promise<Todo> {
return this.todoService.findOne(id);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for findOne method.

The findOne method doesn't handle cases where a todo with the specified ID doesn't exist, which could result in unhandled exceptions.

Consider adding error handling:

  @Get(':id')
  findOne(@Param('id') id: string): Promise<Todo> {
-    return this.todoService.findOne(id);
+    try {
+      return this.todoService.findOne(id);
+    } catch (error) {
+      throw new NotFoundException(`Todo with ID '${id}' not found`);
+    }
  }

Don't forget to import NotFoundException from @nestjs/common.

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +79 to +95
async remove(id: string | number): Promise<void> {
// Obter todos os todos
const todos = await this.todoModel.find().exec();

// Encontrar o todo com id correspondente
const todoToDelete = todos.find(todo => {
const numericId = IdFormatter.toNumber(todo._id);
return numericId.toString() === id.toString();
});

if (!todoToDelete) {
throw new NotFoundException(`Todo with ID ${id} not found`);
}

// Excluir o todo encontrado
await this.todoModel.findByIdAndDelete(todoToDelete._id).exec();
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Optimize the remove method to avoid loading all Todos.

Similar to update(), this method can skip fetching all documents by directly using an ObjectId-based query. It’s more efficient and avoids potential race conditions.

 async remove(id: string | number): Promise<void> {
-  // Obter todos os todos
-  const todos = await this.todoModel.find().exec();
-  
-  // Encontrar o todo com id correspondente
-  const todoToDelete = todos.find(todo => {
-    const numericId = IdFormatter.toNumber(todo._id);
-    return numericId.toString() === id.toString();
-  });
-  
-  if (!todoToDelete) {
-    throw new NotFoundException(\`Todo with ID \${id} not found\`);
-  }
-  
-  // Excluir o todo encontrado
-  await this.todoModel.findByIdAndDelete(todoToDelete._id).exec();
+  const objectId = IdFormatter.toObjectId(id);
+  const deletedTodo = await this.todoModel.findByIdAndDelete(objectId).exec();
+  if (!deletedTodo) {
+    throw new NotFoundException(\`Todo with ID \${id} not found\`);
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async remove(id: string | number): Promise<void> {
// Obter todos os todos
const todos = await this.todoModel.find().exec();
// Encontrar o todo com id correspondente
const todoToDelete = todos.find(todo => {
const numericId = IdFormatter.toNumber(todo._id);
return numericId.toString() === id.toString();
});
if (!todoToDelete) {
throw new NotFoundException(`Todo with ID ${id} not found`);
}
// Excluir o todo encontrado
await this.todoModel.findByIdAndDelete(todoToDelete._id).exec();
}
async remove(id: string | number): Promise<void> {
const objectId = IdFormatter.toObjectId(id);
const deletedTodo = await this.todoModel.findByIdAndDelete(objectId).exec();
if (!deletedTodo) {
throw new NotFoundException(`Todo with ID ${id} not found`);
}
}

Comment on lines +53 to +77
async update(id: string | number, updateTodoDto: UpdateTodoDto): Promise<Todo> {
// Obter todos os todos
const todos = await this.todoModel.find().exec();

// Encontrar o todo com id correspondente
const todoToUpdate = todos.find(todo => {
const numericId = IdFormatter.toNumber(todo._id);
return numericId.toString() === id.toString();
});

if (!todoToUpdate) {
throw new NotFoundException(`Todo with ID ${id} not found`);
}

// Atualizar o todo encontrado
const updatedTodo = await this.todoModel
.findByIdAndUpdate(todoToUpdate._id, updateTodoDto, { new: true })
.exec();

// Converter o _id do MongoDB para um número para compatibilidade com o frontend
const todoObj = updatedTodo.toObject();
todoObj.id = IdFormatter.toNumber(updatedTodo._id);

return todoObj;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Optimize the update method to avoid loading all Todos.

Fetching all Todos and then filtering in memory can be inefficient and prone to race conditions. Directly convert the provided id to an ObjectId and use Mongoose queries to locate, update, and return the document. Also, handle the scenario where findByIdAndUpdate returns null.

 async update(id: string | number, updateTodoDto: UpdateTodoDto): Promise<Todo> {
-  // Obter todos os todos
-  const todos = await this.todoModel.find().exec();
-  
-  // Encontrar o todo com id correspondente
-  const todoToUpdate = todos.find(todo => {
-    const numericId = IdFormatter.toNumber(todo._id);
-    return numericId.toString() === id.toString();
-  });
-  
-  if (!todoToUpdate) {
-    throw new NotFoundException(\`Todo with ID \${id} not found\`);
-  }
-  
-  // Atualizar o todo encontrado
-  const updatedTodo = await this.todoModel
-    .findByIdAndUpdate(todoToUpdate._id, updateTodoDto, { new: true })
-    .exec();
+  const objectId = IdFormatter.toObjectId(id);
+  const updatedTodo = await this.todoModel.findByIdAndUpdate(objectId, updateTodoDto, {
+    new: true,
+  }).exec();
 
  if (!updatedTodo) {
    throw new NotFoundException(\`Todo with ID \${id} not found\`);
  }

  const todoObj = updatedTodo.toObject();
  todoObj.id = IdFormatter.toNumber(updatedTodo._id);
  
  return todoObj;
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async update(id: string | number, updateTodoDto: UpdateTodoDto): Promise<Todo> {
// Obter todos os todos
const todos = await this.todoModel.find().exec();
// Encontrar o todo com id correspondente
const todoToUpdate = todos.find(todo => {
const numericId = IdFormatter.toNumber(todo._id);
return numericId.toString() === id.toString();
});
if (!todoToUpdate) {
throw new NotFoundException(`Todo with ID ${id} not found`);
}
// Atualizar o todo encontrado
const updatedTodo = await this.todoModel
.findByIdAndUpdate(todoToUpdate._id, updateTodoDto, { new: true })
.exec();
// Converter o _id do MongoDB para um número para compatibilidade com o frontend
const todoObj = updatedTodo.toObject();
todoObj.id = IdFormatter.toNumber(updatedTodo._id);
return todoObj;
}
async update(id: string | number, updateTodoDto: UpdateTodoDto): Promise<Todo> {
const objectId = IdFormatter.toObjectId(id);
const updatedTodo = await this.todoModel.findByIdAndUpdate(objectId, updateTodoDto, {
new: true,
}).exec();
if (!updatedTodo) {
throw new NotFoundException(`Todo with ID ${id} not found`);
}
const todoObj = updatedTodo.toObject();
todoObj.id = IdFormatter.toNumber(updatedTodo._id);
return todoObj;
}

Comment on lines +38 to +51
async findOne(id: string | number): Promise<Todo> {
const objectId = IdFormatter.toObjectId(id);
const todo = await this.todoModel.findById(objectId).exec();

if (!todo) {
throw new NotFoundException(`Todo with ID ${id} not found`);
}

// Converter o _id do MongoDB para um número para compatibilidade com o frontend
const todoObj = todo.toObject();
todoObj.id = IdFormatter.toNumber(todo._id);

return todoObj;
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify that invalid IDs are handled.

When converting the id to an ObjectId, ensure that IdFormatter.toObjectId() properly handles invalid strings. Otherwise, the app could throw unhandled cast errors instead of custom exceptions.

Please confirm the behavior of IdFormatter.toObjectId() for invalid inputs by searching for its definition in the codebase:

If it doesn’t handle invalid inputs, consider adding a defensive check or throwing a descriptive error.


🏁 Script executed:

#!/bin/bash
fd "id-formatter.ts" --exec cat {} \
  | rg "toObjectId"

Length of output: 111


I'll run a script to print more lines of the toObjectId method so we can verify whether it handles invalid inputs:


🏁 Script executed:

#!/bin/bash
fd "id-formatter.ts" --exec cat {} \; | rg "static toObjectId" -A 15

Length of output: 702


Action: Update Invalid ID Handling in IdFormatter.toObjectId

After reviewing the code, when an invalid ID string is provided, the current implementation of toObjectId falls back to returning a default ObjectId (123400000000000000000000) instead of throwing a descriptive error. This means that rather than immediately flagging an invalid input, the service proceeds with a lookup and ultimately throws a generic NotFoundException when no Todo is found. This fallback behavior can obscure the root cause of issues when invalid IDs are passed.

  • Location: backend/src/modules/todos/services/todo.service.ts (line 38-51) and id-formatter.ts in the toObjectId method.
  • Issue: Invalid IDs do not trigger a custom error but are silently converted to a default ObjectId.
  • Suggestion: Revise IdFormatter.toObjectId() to either throw a clear, descriptive exception for invalid inputs or document the fallback behavior explicitly. This change will help ensure that callers receive immediate feedback about the invalid input rather than a misleading "not found" error.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (7)
frontend/src/types/ButtonTypes.tsx (4)

1-1: Consider removing the eslint-disable comment.

Starting a file with a linter disable comment is generally not recommended. Instead of disabling Prettier, fix the formatting issues to comply with the project's style guidelines.


2-5: Consider enhancing the ButtonProps interface for better flexibility.

The current interface is minimal but could benefit from additional common button properties like type, disabled, className, etc. This would make the Button component more reusable across the application.

export interface ButtonProps {
    onClick: () => void;
    text: string;
+    type?: 'button' | 'submit' | 'reset';
+    disabled?: boolean;
+    className?: string;
  }

1-6: Use .ts extension for type definition files.

Since this file only contains TypeScript type definitions and no JSX, it should use the .ts extension instead of .tsx.


2-6: Fix indentation inconsistency.

There's inconsistent indentation in the interface definition. The closing brace has extra indentation.

export interface ButtonProps {
    onClick: () => void;
    text: string;
-  }
+}
frontend/src/components/Button/index.tsx (3)

1-1: Consider removing the eslint-disable comment.

Instead of disabling Prettier with a comment, fix the formatting issues to comply with the project's style guidelines.


5-7: Use destructuring for props in function parameters.

Destructuring props in the function signature is a common React pattern that improves readability.

- const Button = (props: ButtonProps) => {
-   return <button onClick={props.onClick}>{props.text}</button>;
+ const Button = ({ onClick, text }: ButtonProps) => {
+   return <button onClick={onClick}>{text}</button>;

5-7: Add styling for the button component.

The button currently lacks any styling. Consider adding CSS or using a styling framework to make it visually appealing and consistent with your application's design system.

- const Button = (props: ButtonProps) => {
-   return <button onClick={props.onClick}>{props.text}</button>;
+ const Button = (props: ButtonProps) => {
+   return (
+     <button 
+       className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors"
+       onClick={props.onClick}
+     >
+       {props.text}
+     </button>
+   );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 12de67e and c4a8d36.

📒 Files selected for processing (2)
  • frontend/src/components/Button/index.tsx (1 hunks)
  • frontend/src/types/ButtonTypes.tsx (1 hunks)

Comment on lines +5 to +7
const Button = (props: ButtonProps) => {
return <button onClick={props.onClick}>{props.text}</button>;
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance the Button component with additional functionality and accessibility features.

The current implementation is basic and could benefit from accessibility improvements and additional customization options.

- const Button = (props: ButtonProps) => {
-   return <button onClick={props.onClick}>{props.text}</button>;
- };
+ const Button = ({ onClick, text, type = 'button', disabled = false, className = '' }: ButtonProps) => {
+   return (
+     <button 
+       onClick={onClick}
+       type={type}
+       disabled={disabled}
+       className={`button ${className}`}
+       aria-label={text}
+     >
+       {text}
+     </button>
+   );
+ };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const Button = (props: ButtonProps) => {
return <button onClick={props.onClick}>{props.text}</button>;
};
const Button = ({ onClick, text, type = 'button', disabled = false, className = '' }: ButtonProps) => {
return (
<button
onClick={onClick}
type={type}
disabled={disabled}
className={`button ${className}`}
aria-label={text}
>
{text}
</button>
);
};

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
frontend/src/lib/api.ts (2)

3-7: Use environment variables for API URL configuration.

Hardcoding the API URL to "http://localhost:3003" makes deployment to different environments challenging. Consider using environment variables for configuration.

-const API = "http://localhost:3003";
+const API = process.env.REACT_APP_API_URL || "http://localhost:3003";

const api = axios.create({
  baseURL: API,
});

11-29: Add error handling and improve type safety.

The API functions lack error handling and use generic any types. Consider adding try/catch blocks and using more specific types.

-export const get = async (path: string): Promise<any> => {
+export const get = async <T = any>(path: string): Promise<T> => {
+  try {
    const response = await api.get(path);
    return response.data;
+  } catch (error) {
+    console.error(`GET request failed for ${path}:`, error);
+    throw error;
+  }
};

-export const post = async (path: string, data: any): Promise<any> => {
+export const post = async <T = any>(path: string, data: unknown): Promise<T> => {
+  try {
    const response = await api.post(path, data);
    return response.data;
+  } catch (error) {
+    console.error(`POST request failed for ${path}:`, error);
+    throw error;
+  }
};

// Apply similar changes to put and del methods
🧹 Nitpick comments (2)
frontend/src/lib/api.ts (2)

9-10: Remove or improve the unused endpoint function.

The endpoint function is defined but never used within this file. Additionally, it directly concatenates the API URL and path without properly handling path separators, which could lead to malformed URLs.

-const endpoint = (path: string): string => API + path;

If you need this function, consider using proper URL joining:

const endpoint = (path: string): string => {
  return path.startsWith('/') ? API + path : `${API}/${path}`;
};

31-31: Consider adding axios interceptors for global error handling.

Since you're exporting the axios instance, you could add interceptors to handle errors globally:

const api = axios.create({
  baseURL: API,
});

+// Add request interceptor
+api.interceptors.request.use(
+  (config) => {
+    // You can add auth tokens or other headers here
+    return config;
+  },
+  (error) => {
+    return Promise.reject(error);
+  }
+);
+
+// Add response interceptor
+api.interceptors.response.use(
+  (response) => {
+    return response;
+  },
+  (error) => {
+    // Handle common errors (401, 403, 500, etc.)
+    if (error.response) {
+      // Handle specific status codes
+      if (error.response.status === 401) {
+        // Handle unauthorized
+      }
+    }
+    return Promise.reject(error);
+  }
+);

export { api };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c4a8d36 and 3c54fa4.

📒 Files selected for processing (3)
  • backend/src/main.ts (1 hunks)
  • frontend/src/components/DeleteModal/index.tsx (1 hunks)
  • frontend/src/lib/api.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • backend/src/main.ts
  • frontend/src/components/DeleteModal/index.tsx

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