Skip to content

Feat: Implement CRUD for project links and notes with UX improvements - #11

Merged
MathCunha16 merged 4 commits into
mainfrom
feature/frontend/api-implementation-links-notes-and-tags
Jul 22, 2026
Merged

Feat: Implement CRUD for project links and notes with UX improvements#11
MathCunha16 merged 4 commits into
mainfrom
feature/frontend/api-implementation-links-notes-and-tags

Conversation

@MathCunha16

@MathCunha16 MathCunha16 commented Jul 21, 2026

Copy link
Copy Markdown
Owner

This pull request introduces a new tags management modal for the frontend and adds API and UI support for managing project links. It also fixes a typo in a backend controller route. The main changes are grouped below.

Tags Management Modal (Frontend)

  • Added a new TagsManagerModal React component with full CRUD functionality for tags, including color selection, inline editing, deletion with confirmation, and keyboard accessibility features. (frontend/src/components/TagsManagerModal.tsx)
  • Introduced a comprehensive CSS module for the tags manager modal, providing styles for the modal overlay, form elements, tag list, and interactive states. (frontend/src/components/TagsManagerModal.module.css)

Project Links API and UI Support

  • Implemented a new linksApi module to handle all CRUD operations for project links via the backend API. (frontend/src/features/links/api/linksApi.ts)
  • Added a CSS module for a new or updated link form modal, supporting form layout, modal presentation, and button styling. (frontend/src/features/links/components/LinkForm.module.css)

Backend Route Fix

  • Fixed a typo in the NoteController backend route, changing /ap1/v1/... to /api/v1/... for correct API endpoint addressing. (backend/src/main/java/com/devaulty/backend/adapter/in/web/note/NoteController.java)

Summary by CodeRabbit

  • Novos Recursos

    • Adicionadas áreas de Notas do Sistema e Links Web no workspace, com abas dedicadas.
    • Notas agora permitem criar, editar, excluir, arquivar e desarquivar.
    • Links agora permitem criar e editar em modais, além de remoção.
    • Gerenciamento avançado de tags com busca, criação, edição e exclusão, incluindo associação de tags também para notas e links.
  • Correções

    • Ajustado o caminho das rotas REST de notas para garantir o funcionamento dos endpoints.

@MathCunha16 MathCunha16 self-assigned this Jul 21, 2026
@MathCunha16 MathCunha16 added enhancement New feature or request Frontend Frontend feature or modification labels Jul 21, 2026
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 2c29375d-0a81-40a3-be1f-d29f14ec2146

📥 Commits

Reviewing files that changed from the base of the PR and between 0b31a81 and 8c38aa9.

📒 Files selected for processing (2)
  • frontend/src/features/links/components/LinkForm.tsx
  • frontend/src/features/notes/components/NoteForm.tsx

📝 Walkthrough

Walkthrough

O PR adiciona suporte a notas e links no workspace, com APIs, modelos, queries, mutations, formulários modais e gerenciamento de tags. Também amplia as associações de tags e corrige o prefixo das rotas REST de notas e seus testes.

Changes

Conteúdo do workspace

Layer / File(s) Summary
Contratos e acesso a dados
frontend/src/types/api.ts, frontend/src/features/notes/..., frontend/src/features/links/..., frontend/src/features/tags/...
Modelos, clientes HTTP e hooks React Query passam a cobrir notas, links, busca e atualização de tags.
Formulários de notas e links
frontend/src/features/notes/components/*, frontend/src/features/links/components/*
Modais de criação e edição validam campos, carregam detalhes, executam mutations e exibem feedback.
Modal de gerenciamento de tags
frontend/src/components/TagsManagerModal.*
Permite criar, buscar, editar e excluir tags com confirmação, focus trap e estilos próprios.
Integração no workspace
frontend/src/components/ProjectDetailView.tsx
Adiciona abas, filtros, ações, popovers de tags e modais globais para Notes e Links.

Rota REST de notas

Layer / File(s) Summary
Correção do mapeamento REST
backend/src/main/java/.../NoteController.java, backend/src/test/java/.../NoteControllerIT.java
Atualiza o prefixo das rotas de notas de /ap1 para /api no controller e nos testes de integração.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ProjectDetailView
  participant NoteForm
  participant useCreateNoteMutation
  participant notesApi
  User->>ProjectDetailView: abre o formulário de nota
  ProjectDetailView->>NoteForm: renderiza modal de criação
  User->>NoteForm: envia título e conteúdo
  NoteForm->>useCreateNoteMutation: submete dados
  useCreateNoteMutation->>notesApi: cria nota
  notesApi-->>useCreateNoteMutation: retorna sucesso
  useCreateNoteMutation-->>ProjectDetailView: invalida a lista de notas
  ProjectDetailView-->>User: exibe a nota atualizada
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed O título descreve corretamente a adição de CRUD para links e notas e os aprimoramentos de UX, que são partes centrais do PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (5)
frontend/src/features/tags/hooks/useTags.ts (2)

74-78: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Mapeamento itemType → itemKey duplicado entre useAssociateTagMutation e useDisassociateTagMutation.

A mesma lógica if/else-if de mapeamento de typeLower para a chave de invalidação (snippets/problems/notes/links) está repetida nas duas mutations. Centralizar em uma função utilitária evita divergência futura (como a que já ocorreu em useUpdateTagMutation, cuja lista de invalidação ficou incompleta por não reaproveitar esse mapeamento).

  • frontend/src/features/tags/hooks/useTags.ts#L74-L78: extrair a lógica de useAssociateTagMutation para uma função getItemKeyForType(itemType: string): string compartilhada.
  • frontend/src/features/tags/hooks/useTags.ts#L90-L94: reutilizar a mesma função getItemKeyForType em useDisassociateTagMutation em vez de duplicar o if/else-if.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/features/tags/hooks/useTags.ts` around lines 74 - 78, Centralize
the duplicated itemType-to-itemKey mapping in a shared
getItemKeyForType(itemType: string): string function. Update
useAssociateTagMutation at frontend/src/features/tags/hooks/useTags.ts:74-78 to
use the helper, and update useDisassociateTagMutation at
frontend/src/features/tags/hooks/useTags.ts:90-94 to reuse it instead of
maintaining a separate if/else-if chain.

18-25: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

useSearchTagsQuery sem debounce pode gerar excesso de requisições.

A query é habilitada a cada mudança de name não vazio, sem debounce. Se usada em um campo de busca "ao digitar", isso disparará um GET por tecla.

Verifique como esse hook é consumido (ex.: popover de tags em ProjectDetailView.tsx) para confirmar se já existe debounce no lado do chamador antes de decidir se o ajuste deve entrar aqui ou lá.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/features/tags/hooks/useTags.ts` around lines 18 - 25, Verifique
os consumidores de useSearchTagsQuery, especialmente o popover de tags em
ProjectDetailView.tsx, para confirmar se name já é debounceado antes da
consulta. Se não houver debounce no chamador, adicione debounce ao fluxo de
busca preservando o enabled para nomes não vazios e use o valor debounced em
tagsKeys.search e tagsApi.search; se já existir, mantenha o hook sem duplicar o
atraso.
frontend/src/features/notes/hooks/useNotes.ts (1)

40-43: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Invalidação redundante antes de setQueryData na mutation de update.

invalidateQueries para notesKeys.detail dispara um refetch imediato (comportamento padrão do React Query v5 para queries ativas) para a mesma chave que é sobrescrita na linha seguinte com setQueryData. Isso gera uma requisição de rede desnecessária sempre que a nota editada estiver montada.

♻️ Ajuste sugerido
     onSuccess: (data) => {
       queryClient.invalidateQueries({ queryKey: notesKeys.all(projectId) });
-      queryClient.invalidateQueries({ queryKey: notesKeys.detail(projectId, noteId) });
       queryClient.setQueryData(notesKeys.detail(projectId, noteId), data);
     },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/features/notes/hooks/useNotes.ts` around lines 40 - 43, Remova a
invalidação de notesKeys.detail dentro do callback onSuccess da mutation de
atualização, mantendo a invalidação de notesKeys.all e a atualização direta via
setQueryData para a nota editada.
frontend/src/components/TagsManagerModal.tsx (1)

45-75: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Lógica de foco duplicada em relação ao ConfirmModal.

Os dois useEffects de restauração de foco e Tab-trap replicam exatamente o padrão já implementado em ConfirmModal.tsx. Extrair um hook compartilhado (ex.: useFocusTrap(modalRef, isOpen, initialFocusRef)) reduziria a manutenção duplicada, especialmente se outros modais (NoteForm/LinkForm) repetirem o mesmo padrão.

Also applies to: 77-110

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/TagsManagerModal.tsx` around lines 45 - 75, Extraia a
lógica compartilhada de captura, foco inicial, restauração de foco e Tab-trap
presente em TagsManagerModal e ConfirmModal para um hook reutilizável, como
useFocusTrap. Atualize ambos os componentes para usar esse hook com modalRef,
isOpen e a ref do foco inicial, removendo os useEffect e refs duplicados sem
alterar o comportamento existente.
frontend/src/features/links/hooks/useLinks.ts (1)

11-16: 🚀 Performance & Scalability | 🔵 Trivial

Paginação fixa em size = 100.

A busca/filtragem em ProjectDetailView (filteredLinks/filteredNotes) é feita no cliente sobre content, então links (e notas, que seguem o mesmo padrão) além dos primeiros 100 ficam invisíveis e não pesquisáveis. Para projetos com muitos itens, considere paginação incremental (ex.: useInfiniteQuery) ou busca server-side.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/features/links/hooks/useLinks.ts` around lines 11 - 16, Update
useLinksQuery and the ProjectDetailView filteredLinks/filteredNotes flow so
client-side search can access all project links and notes instead of only the
first 100; implement incremental pagination (such as useInfiniteQuery) and
aggregate all fetched pages before filtering, or reuse an existing server-side
search mechanism if available.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@backend/src/main/java/com/devaulty/backend/adapter/in/web/note/NoteController.java`:
- Line 24: Atualize o endpoint definido em NoteController e todos os
consumidores relacionados, incluindo NoteControllerIT, para usar o prefixo
correto /api/v1/projects/{projectId}/notes em vez de /ap1/v1. Preserve o
restante do caminho e dos comportamentos existentes.

In `@frontend/src/components/TagsManagerModal.tsx`:
- Around line 280-289: Adicione um nome acessível a cada botão de cor no
mapeamento PRESET_COLORS do formulário de edição inline, usando title e/ou
aria-label com o valor da cor, mantendo o comportamento existente de
setEditingTagColor.
- Around line 355-365: Update the warningText in the Delete Confirmation Modal
to mention that deleting the tag will disassociate it from snippets, problems,
notes, and links across the project. Leave the confirmDeleteTag flow and other
modal properties unchanged.

In `@frontend/src/features/notes/components/NoteForm.tsx`:
- Around line 63-93: Update the keydown handlers in NoteForm.tsx (lines 63-93)
and LinkForm.tsx (lines 65-95) to call onClose() when e.key is "Escape", while
preserving the existing Tab focus-trap behavior.
- Around line 276-293: Remove the unused Suspense wrappers and their loading
fallbacks around EditNoteFormModal in NoteForm.tsx (lines 276-293) and
EditLinkFormModal in LinkForm.tsx (lines 300-316), since both components handle
useQuery loading states internally; leave the modal rendering and props
unchanged.

In `@frontend/src/features/tags/hooks/useTags.ts`:
- Around line 41-46: Atualize o callback onSuccess de useUpdateTagMutation para
também invalidar as queries de notas e links do projeto, usando as chaves de
cache já empregadas por useAssociateTagMutation e useDisassociateTagMutation.
Preserve as invalidações existentes de tags, problems e snippets.

---

Nitpick comments:
In `@frontend/src/components/TagsManagerModal.tsx`:
- Around line 45-75: Extraia a lógica compartilhada de captura, foco inicial,
restauração de foco e Tab-trap presente em TagsManagerModal e ConfirmModal para
um hook reutilizável, como useFocusTrap. Atualize ambos os componentes para usar
esse hook com modalRef, isOpen e a ref do foco inicial, removendo os useEffect e
refs duplicados sem alterar o comportamento existente.

In `@frontend/src/features/links/hooks/useLinks.ts`:
- Around line 11-16: Update useLinksQuery and the ProjectDetailView
filteredLinks/filteredNotes flow so client-side search can access all project
links and notes instead of only the first 100; implement incremental pagination
(such as useInfiniteQuery) and aggregate all fetched pages before filtering, or
reuse an existing server-side search mechanism if available.

In `@frontend/src/features/notes/hooks/useNotes.ts`:
- Around line 40-43: Remova a invalidação de notesKeys.detail dentro do callback
onSuccess da mutation de atualização, mantendo a invalidação de notesKeys.all e
a atualização direta via setQueryData para a nota editada.

In `@frontend/src/features/tags/hooks/useTags.ts`:
- Around line 74-78: Centralize the duplicated itemType-to-itemKey mapping in a
shared getItemKeyForType(itemType: string): string function. Update
useAssociateTagMutation at frontend/src/features/tags/hooks/useTags.ts:74-78 to
use the helper, and update useDisassociateTagMutation at
frontend/src/features/tags/hooks/useTags.ts:90-94 to reuse it instead of
maintaining a separate if/else-if chain.
- Around line 18-25: Verifique os consumidores de useSearchTagsQuery,
especialmente o popover de tags em ProjectDetailView.tsx, para confirmar se name
já é debounceado antes da consulta. Se não houver debounce no chamador, adicione
debounce ao fluxo de busca preservando o enabled para nomes não vazios e use o
valor debounced em tagsKeys.search e tagsApi.search; se já existir, mantenha o
hook sem duplicar o atraso.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: ede4b7dc-dafc-4bbd-abbb-9b625f65c4eb

📥 Commits

Reviewing files that changed from the base of the PR and between b532f34 and 0f81955.

📒 Files selected for processing (15)
  • backend/src/main/java/com/devaulty/backend/adapter/in/web/note/NoteController.java
  • frontend/src/components/ProjectDetailView.tsx
  • frontend/src/components/TagsManagerModal.module.css
  • frontend/src/components/TagsManagerModal.tsx
  • frontend/src/features/links/api/linksApi.ts
  • frontend/src/features/links/components/LinkForm.module.css
  • frontend/src/features/links/components/LinkForm.tsx
  • frontend/src/features/links/hooks/useLinks.ts
  • frontend/src/features/notes/api/notesApi.ts
  • frontend/src/features/notes/components/NoteForm.module.css
  • frontend/src/features/notes/components/NoteForm.tsx
  • frontend/src/features/notes/hooks/useNotes.ts
  • frontend/src/features/tags/api/tagsApi.ts
  • frontend/src/features/tags/hooks/useTags.ts
  • frontend/src/types/api.ts

Comment thread frontend/src/components/TagsManagerModal.tsx
Comment thread frontend/src/components/TagsManagerModal.tsx
Comment thread frontend/src/features/notes/components/NoteForm.tsx Outdated
Comment thread frontend/src/features/notes/components/NoteForm.tsx
Comment thread frontend/src/features/tags/hooks/useTags.ts
…endpoint typos in integration tests, and update tag invalidation logic

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/features/notes/components/NoteForm.tsx (1)

63-97: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Inclua onClose nas dependências do efeito. O handler captura a versão inicial do callback; como o pai passa onClose inline, um rerender com o modal aberto pode deixar o Escape chamando uma referência obsoleta.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/features/notes/components/NoteForm.tsx` around lines 63 - 97,
Atualize as dependências do useEffect que registra o handler de teclado em
NoteForm para incluir onClose, garantindo que o Escape use a referência atual do
callback quando o componente pai rerenderizar.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/features/notes/components/NoteForm.tsx`:
- Around line 65-68: Prevent Escape and overlay-click handlers from calling
onClose while isSubmitting in NoteForm.tsx and LinkForm.tsx. Update the relevant
useEffect handlers in both components to include isSubmitting in their
dependency arrays, while preserving closing behavior when submission is not
pending.

---

Outside diff comments:
In `@frontend/src/features/notes/components/NoteForm.tsx`:
- Around line 63-97: Atualize as dependências do useEffect que registra o
handler de teclado em NoteForm para incluir onClose, garantindo que o Escape use
a referência atual do callback quando o componente pai rerenderizar.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 103eb30c-a559-4bf1-bae6-c6be430acef0

📥 Commits

Reviewing files that changed from the base of the PR and between 0f81955 and 0b31a81.

📒 Files selected for processing (6)
  • backend/src/test/java/com/devaulty/backend/adapter/in/web/note/NoteControllerIT.java
  • frontend/src/components/TagsManagerModal.module.css
  • frontend/src/components/TagsManagerModal.tsx
  • frontend/src/features/links/components/LinkForm.tsx
  • frontend/src/features/notes/components/NoteForm.tsx
  • frontend/src/features/tags/hooks/useTags.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • frontend/src/features/tags/hooks/useTags.ts
  • frontend/src/components/TagsManagerModal.tsx
  • frontend/src/components/TagsManagerModal.module.css

Comment thread frontend/src/features/notes/components/NoteForm.tsx
  submission

    Prevent NoteForm and LinkForm from closing when the user presses the
  Escape key or clicks the overlay background while form submission is in
  progress. Updated the keydown useEffect hook dependencies and overlay
  onClick handlers to check and respect the isSubmitting state.
@MathCunha16
MathCunha16 merged commit aaf9f4f into main Jul 22, 2026
1 check was pending
@MathCunha16
MathCunha16 deleted the feature/frontend/api-implementation-links-notes-and-tags branch July 22, 2026 03:09
@coderabbitai coderabbitai Bot mentioned this pull request Aug 14, 2026
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request Frontend Frontend feature or modification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant