Skip to content

Reordering curation drops#2272

Open
ragnep wants to merge 6 commits intomainfrom
reordering-curations
Open

Reordering curation drops#2272
ragnep wants to merge 6 commits intomainfrom
reordering-curations

Conversation

@ragnep
Copy link
Copy Markdown
Contributor

@ragnep ragnep commented Apr 15, 2026

Summary by CodeRabbit

  • New Features

    • Added drag-and-drop reordering functionality for wave curation drops with a visual reorder mode toggle.
    • Added confirmation dialog when clearing profile wave selections for enhanced safety.
    • Introduced new drag handle icon for initiating reorder operations.
  • Improvements

    • Enhanced pagination error handling with explicit rejection management.
    • Optimized curation data fetching with improved authentication context integration.

ragnep added 5 commits April 15, 2026 08:32
Signed-off-by: ragnep <ragneinfo@gmail.com>
Signed-off-by: ragnep <ragneinfo@gmail.com>
Signed-off-by: ragnep <ragneinfo@gmail.com>
Signed-off-by: ragnep <ragneinfo@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 15, 2026

Warning

Rate limit exceeded

@ragnep has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 46 minutes and 17 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 46 minutes and 17 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4fe86a1f-3b45-46a1-ae35-efec131a0345

📥 Commits

Reviewing files that changed from the base of the PR and between 4e36a3a and c8c4f39.

📒 Files selected for processing (5)
  • components/user/waves/UserPageProfileWave.tsx
  • components/user/waves/UserPageProfileWaveMasonry.tsx
  • components/user/waves/UserPageProfileWaveMasonryCard.tsx
  • hooks/drops/useDropCurationOrderMutation.ts
  • openapi.yaml
📝 Walkthrough

Walkthrough

This pull request introduces wave curation drop reordering functionality using dnd-kit for drag-and-drop interactions. Changes include a new useWaveCurationDrops hook for fetching paginated drops, drop order mutation/persistence logic, UI state and components for reorder mode in profile waves, a new MoveIcon component for drag handles, and OpenAPI schema extensions for priority order fields.

Changes

Cohort / File(s) Summary
Wave Curation Drops Hooks
hooks/useWaveCurationDrops.ts, hooks/drops/useDropCurationOrderMutation.ts, hooks/drops/useDropCurations.ts
New useWaveCurationDrops hook with paginated infinite-query fetching, websocket DROP_UPDATE listener, and fetchAllWaveCurationDrops helper. New useDropCurationOrderMutation hook to persist reordered drops. Extended useDropCurations to include authentication context in cache keys and prevent queries during profile fetches.
Permission & Membership Hooks
hooks/useCurationManagementPermission.ts, hooks/drops/useDropCurationMembershipMutation.ts
Added optional enabled parameter to useCurationManagementPermission. Refactored useDropCurationMembershipMutation to use centralized postDropCuration and deleteDropCuration API functions with improved query key handling.
Profile Wave Components
components/user/waves/UserPageProfileWave.tsx, components/user/waves/UserPageProfileWaveMasonry.tsx
Added reorder mode state, confirmation modals for clear actions, and new props (canManageProfileWave, isReorderMode, onReorderModeChange). Replaced masonic masonry with custom column builder and dnd-kit sortable implementation with drag handles, order persistence, and dragging visual states.
Wave Curation Content
components/brain/my-stream/curations/MyStreamWaveCurationContent.tsx
Switched from useWaveDrops to useWaveCurationDrops hook and updated fetchNextPage error handling with explicit .catch() instead of void operator.
UI Components & Icons
components/utils/icons/MoveIcon.tsx
New drag-handle icon component with four-directional move arrows and customizable className prop.
API Layer
services/api/drop-curations-api.ts, openapi.yaml
New postDropCuration and deleteDropCuration API functions. OpenAPI schema additions: new /waves/{id}/curations/{curation_id}/drops GET endpoint, priority_order field in ApiDropCuration/ApiWaveCuration/ApiWaveCurationRequest, new ApiCurationDrop and ApiCurationDropsPage schemas.
Dependencies
package.json
Added dnd-kit packages: @dnd-kit/core (6.3.1), @dnd-kit/sortable (10.0.0), @dnd-kit/utilities (3.2.2).

Sequence Diagrams

sequenceDiagram
    actor User
    participant UI as UserPageProfileWaveMasonry
    participant DnD as dnd-kit
    participant State as Local Reorder State
    participant API as useDropCurationOrderMutation
    participant Server as API Server
    participant Cache as React Query Cache

    User->>UI: Enable reorder mode
    UI->>UI: fetchAllWaveCurationDrops()
    UI->>Server: GET /waves/{id}/curations/{curationId}/drops
    Server-->>UI: All drops with order IDs
    UI->>State: Initialize persistedOrderIdsRef
    
    User->>DnD: Drag drop to new position
    DnD->>UI: handleDragEnd(event)
    UI->>State: Reorder drops locally
    UI->>UI: Render with new visual order
    
    UI->>API: persistOrderAsync(updates)
    API->>Server: POST /api/drops/{dropId}/curations
    alt Success
        Server-->>API: Order updated
        API->>Cache: invalidateDrops()
        Cache-->>UI: Refetch drop data
        UI->>State: Keep local reorder state
    else Failure
        Server-->>API: Error response
        API->>UI: setToast(error)
        UI->>State: Revert to persistedOrderIdsRef
    end
Loading
sequenceDiagram
    participant App as App
    participant Hook as useWaveCurationDrops
    participant RQ as React Query
    participant WS as WebSocket
    participant API as API Server

    App->>Hook: useWaveCurationDrops({wave, curationId})
    Hook->>RQ: useInfiniteQuery(createKey)
    RQ->>API: GET /waves/{id}/curations/{curationId}/drops?page=0
    API-->>RQ: Page 1 drops with nextPageParam
    RQ-->>Hook: drops[], hasNextPage, etc.
    
    App->>Hook: fetchNextPage()
    Hook->>RQ: fetchNextPage()
    RQ->>API: GET /waves/{id}/curations/{curationId}/drops?page=1
    API-->>RQ: Page 2 drops
    
    WS->>Hook: DROP_UPDATE event (wave.id matches)
    Hook->>Hook: useDebouncedQueryRefetch()
    Hook->>RQ: refetch()
    RQ->>API: GET /waves/{id}/curations/{curationId}/drops?page=0
    API-->>RQ: Refreshed drops
    RQ-->>App: Updated drops array
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • removed curation list view #2269: Modifies UserPageProfileWave.tsx to remove list view toggle; this PR further extends that component with reorder mode, confirmation flows, and state management changes.
  • curation view #2227: Introduces/modifies MyStreamWaveCurationContent.tsx; this PR switches that component from useWaveDrops to the new useWaveCurationDrops hook.
  • profile wave selection #2259: Also modifies MyStreamWaveCurationContent.tsx and wave curation permission/drop sourcing logic related to this PR's refactoring.

Suggested reviewers

  • simo6529
  • GelatoGenesis

Poem

🐰 Hop, drag, and drop with glee,
Reordering waves in perfect harmony,
With dnd-kit's graceful embrace,
Drops find their destined place,
Priority orders dance so free!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'Reordering curation drops' accurately and directly describes the main feature added across the changeset: drag-and-drop reordering functionality for curation drops with associated UI, hooks, and API changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch reordering-curations

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

@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: 5

Caution

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

⚠️ Outside diff range comments (1)
openapi.yaml (1)

8634-8645: ⚠️ Potential issue | 🔴 Critical

ApiDropGroupMention is malformed and currently makes the spec invalid.

Lines 8634–8645 contain a schema definition that mixes a scalar enum (type: string, enum: [ALL]) with an object property (priority_order), violating YAML and OpenAPI syntax. The same schema name is declared twice immediately after. The YAML parser fails at line 8638 with "expected , but found '?'" because priority_order is indented at the list item level rather than as a separate object field. This must be resolved to a single, valid schema shape before the spec can be parsed and used for validation or code generation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openapi.yaml` around lines 8634 - 8645, The ApiDropGroupMention schema is
malformed: remove the duplicated scalar enum declaration and consolidate into a
single valid schema shape (either keep it as a string enum OR make it an object
with properties), e.g., if you need priority_order attach it under
ApiDropGroupMention as properties.priority_order with type integer, format int64
and minimum 1 and move the enum into a valid property (or drop the enum
entirely); ensure only one ApiDropGroupMention definition exists and that
priority_order is indented as a properties field rather than at the enum list
level.
🧹 Nitpick comments (4)
openapi.yaml (2)

6051-6067: Align the curation path parameter name with the sibling routes.

This route uses {curation_id} while the update/delete routes use {curationId} for the same resource. That inconsistency leaks into generated client signatures and makes the same identifier appear under two public names.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openapi.yaml` around lines 6051 - 6067, The path parameter name in the route
"/waves/{id}/curations/{curation_id}/drops" is inconsistent with sibling routes;
change the path segment and parameter definition from "{curation_id}" to
"{curationId}" so the OpenAPI path and the parameters block use the same
identifier, and update any references used by operationId
"listWaveCurationDrops" to match the new name.

8365-8387: Tighten the ordering contract for curation members.

These schemas introduce drop_priority_order for reorder flows, but still allow null. For ApiCurationDrop in particular, the endpoint only returns drops already in the curation, so clients cannot rely on a stable persisted position from the schema. Either make that field non-null there, or document the exact null case and keep it limited to ApiDropCuration.

Also applies to: 8614-8626

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openapi.yaml` around lines 8365 - 8387, ApiCurationDrop currently allows
drop_priority_order to be null, but the endpoint returns only drops already in
the curation so clients expect a stable position; update the OpenAPI schemas so
ApiCurationDrop's drop_priority_order is non-nullable (remove or set nullable:
false) and keep nullable only on the input/update schema (e.g., ApiDropCuration)
if you must accept null for reorder payloads, or alternatively add explicit
documentation to ApiCurationDrop describing the null case — change the schema
definition for ApiCurationDrop (and mirror the same decision for the other
occurrence at the referenced lines) so the contract is consistent.
hooks/useWaveCurationDrops.ts (1)

122-149: No upper bound on page fetching could cause performance issues.

fetchAllWaveCurationDrops fetches all pages in an unbounded loop. For curations with a very large number of drops, this could result in excessive API calls and memory usage, potentially degrading user experience.

Consider adding a maximum page limit or total items cap as a safety measure.

♻️ Proposed safety limit
+const MAX_FETCH_ALL_PAGES = 50;
+
 export const fetchAllWaveCurationDrops = async ({
   wave,
   curationId,
   pageSize = MAX_CURATION_DROPS_PAGE_SIZE,
 }: {
   readonly wave: ApiWave;
   readonly curationId: string;
   readonly pageSize?: number | undefined;
 }): Promise<ExtendedDrop[]> => {
   const pages: ApiCurationDropsPage[] = [];
   let nextPage = 1;
   let hasNextPage = true;

-  while (hasNextPage) {
+  while (hasNextPage && nextPage <= MAX_FETCH_ALL_PAGES) {
     const page = await fetchWaveCurationDropsPage({
       waveId: wave.id,
       curationId,
       page: nextPage,
       pageSize,
     });

     pages.push(page);
     hasNextPage = page.next;
     nextPage = page.page + 1;
   }

   return processDrops(pages, wave);
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@hooks/useWaveCurationDrops.ts` around lines 122 - 149,
fetchAllWaveCurationDrops currently loops unboundedly calling
fetchWaveCurationDropsPage and can exhaust memory/API for very large curations;
add a safety cap (e.g., maxPages or maxItems) to stop fetching after a
reasonable limit and surface that limit via a new optional parameter (e.g.,
maxPages?: number or maxItems?: number) with a sensible default constant (e.g.,
MAX_CURATION_DROPS_MAX_PAGES), update the while loop to break when the cap is
reached, and ensure processDrops is called on the pages fetched; reference
fetchAllWaveCurationDrops, fetchWaveCurationDropsPage,
MAX_CURATION_DROPS_PAGE_SIZE, and processDrops when making the change.
components/user/waves/UserPageProfileWave.tsx (1)

296-301: Consider optimizing the permission check.

useWaveCurationDrops is called solely to determine if curationDrops.length > 1 for the canReorder check. This triggers a full paginated fetch of drops when you only need to know if there's more than one drop.

If the API supports it, consider a lighter endpoint or using a count-only query. Otherwise, this is acceptable for now as the data is likely cached or shared.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/user/waves/UserPageProfileWave.tsx` around lines 296 - 301, The
current call to useWaveCurationDrops (used to compute canReorder) fetches full
paginated drop data just to check if there are more than one item; replace this
with a lightweight check by calling a count/summary endpoint or requesting only
two items (e.g., limit=2 or a minimal fields projection) so you avoid full
pagination. Update the logic around useWaveCurationDrops / curationDrops (and
the derived canReorder) to use the new lightweight hook or query (or add a new
useWaveCurationCount hook) that accepts wave and curationId
(profileCuration?.id) and enabled (canClear && !!profileCuration) and returns a
count or a small array; then compute canReorder from count > 1 or
returned.length > 1.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/user/waves/UserPageProfileWave.tsx`:
- Around line 550-553: The confirmUnavailableClearProfileWave function currently
awaits clearSelectedProfileWave() and then unconditionally closes the modal via
setIsUnavailableClearConfirmOpen(false); wrap the await in a try/catch and only
call setIsUnavailableClearConfirmOpen(false) when clearSelectedProfileWave
resolves successfully, leaving the modal open on error so the user can see the
failure (mirror the behavior needed for confirmClearProfileWave); surface or
rethrow the caught error so existing error UI/notifications can display it.
- Around line 331-334: confirmClearProfileWave currently awaits
clearSelectedProfileWave() then unconditionally calls
setIsClearConfirmOpen(false), which will close the modal even if persistence
fails; change confirmClearProfileWave to only close the modal on success by
wrapping the await in a try/catch: call await clearSelectedProfileWave() inside
try, then call setIsClearConfirmOpen(false) after a successful await, and handle
errors in catch (e.g., surface the error via existing error handler/UI instead
of closing the modal). Ensure you reference confirmClearProfileWave,
clearSelectedProfileWave, and setIsClearConfirmOpen when making the change.

In `@hooks/drops/useDropCurationOrderMutation.ts`:
- Around line 25-37: The current batch update uses Promise.all over updates.map
calling postDropCuration, which will reject immediately on the first failure and
leave partial updates untracked; replace Promise.all with Promise.allSettled in
the function that performs the batch (the updates.map / postDropCuration block
inside useDropCurationOrderMutation) and iterate the settled results to separate
successes from failures, retry or roll back failed items as appropriate, collect
failed dropIds and error messages, and surface a consolidated error state or
toast to the UI so callers can reconcile partial failures rather than silently
failing on the first error.

In `@openapi.yaml`:
- Around line 977-992: The GET /light-drops operation currently defines the
query parameters min_serial_no and older_first twice; remove the duplicated
parameter definitions so each (name, in) pair appears only once in the
operation. Keep the canonical definitions for min_serial_no (type integer,
format int64, minimum 1) and older_first (type boolean) and, if the two blocks
differ, merge any unique description text into the remaining single definitions
for min_serial_no and older_first to preserve intent.

In `@services/api/drop-curations-api.ts`:
- Around line 6-7: The getDropCurationEndpoint helper inserts dropId directly
into the URL path which can break if dropId contains reserved characters; update
getDropCurationEndpoint (and any other uses around the other occurrence) to
encode the path segment by applying encodeURIComponent to dropId before
concatenation so the generated endpoint is safe when dropId contains "/", "?",
"#", etc.

---

Outside diff comments:
In `@openapi.yaml`:
- Around line 8634-8645: The ApiDropGroupMention schema is malformed: remove the
duplicated scalar enum declaration and consolidate into a single valid schema
shape (either keep it as a string enum OR make it an object with properties),
e.g., if you need priority_order attach it under ApiDropGroupMention as
properties.priority_order with type integer, format int64 and minimum 1 and move
the enum into a valid property (or drop the enum entirely); ensure only one
ApiDropGroupMention definition exists and that priority_order is indented as a
properties field rather than at the enum list level.

---

Nitpick comments:
In `@components/user/waves/UserPageProfileWave.tsx`:
- Around line 296-301: The current call to useWaveCurationDrops (used to compute
canReorder) fetches full paginated drop data just to check if there are more
than one item; replace this with a lightweight check by calling a count/summary
endpoint or requesting only two items (e.g., limit=2 or a minimal fields
projection) so you avoid full pagination. Update the logic around
useWaveCurationDrops / curationDrops (and the derived canReorder) to use the new
lightweight hook or query (or add a new useWaveCurationCount hook) that accepts
wave and curationId (profileCuration?.id) and enabled (canClear &&
!!profileCuration) and returns a count or a small array; then compute canReorder
from count > 1 or returned.length > 1.

In `@hooks/useWaveCurationDrops.ts`:
- Around line 122-149: fetchAllWaveCurationDrops currently loops unboundedly
calling fetchWaveCurationDropsPage and can exhaust memory/API for very large
curations; add a safety cap (e.g., maxPages or maxItems) to stop fetching after
a reasonable limit and surface that limit via a new optional parameter (e.g.,
maxPages?: number or maxItems?: number) with a sensible default constant (e.g.,
MAX_CURATION_DROPS_MAX_PAGES), update the while loop to break when the cap is
reached, and ensure processDrops is called on the pages fetched; reference
fetchAllWaveCurationDrops, fetchWaveCurationDropsPage,
MAX_CURATION_DROPS_PAGE_SIZE, and processDrops when making the change.

In `@openapi.yaml`:
- Around line 6051-6067: The path parameter name in the route
"/waves/{id}/curations/{curation_id}/drops" is inconsistent with sibling routes;
change the path segment and parameter definition from "{curation_id}" to
"{curationId}" so the OpenAPI path and the parameters block use the same
identifier, and update any references used by operationId
"listWaveCurationDrops" to match the new name.
- Around line 8365-8387: ApiCurationDrop currently allows drop_priority_order to
be null, but the endpoint returns only drops already in the curation so clients
expect a stable position; update the OpenAPI schemas so ApiCurationDrop's
drop_priority_order is non-nullable (remove or set nullable: false) and keep
nullable only on the input/update schema (e.g., ApiDropCuration) if you must
accept null for reorder payloads, or alternatively add explicit documentation to
ApiCurationDrop describing the null case — change the schema definition for
ApiCurationDrop (and mirror the same decision for the other occurrence at the
referenced lines) so the contract is consistent.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1ed5878c-2b30-4e7f-a90a-7c00eba9fc86

📥 Commits

Reviewing files that changed from the base of the PR and between 2e56b4f and 4e36a3a.

⛔ Files ignored due to path filters (8)
  • generated/models/ApiCurationDrop.ts is excluded by !**/generated/**
  • generated/models/ApiCurationDropsPage.ts is excluded by !**/generated/**
  • generated/models/ApiDropCuration.ts is excluded by !**/generated/**
  • generated/models/ApiDropCurationRequest.ts is excluded by !**/generated/**
  • generated/models/ApiWaveCuration.ts is excluded by !**/generated/**
  • generated/models/ApiWaveCurationRequest.ts is excluded by !**/generated/**
  • generated/models/ObjectSerializer.ts is excluded by !**/generated/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (12)
  • components/brain/my-stream/curations/MyStreamWaveCurationContent.tsx
  • components/user/waves/UserPageProfileWave.tsx
  • components/user/waves/UserPageProfileWaveMasonry.tsx
  • components/utils/icons/MoveIcon.tsx
  • hooks/drops/useDropCurationMembershipMutation.ts
  • hooks/drops/useDropCurationOrderMutation.ts
  • hooks/drops/useDropCurations.ts
  • hooks/useCurationManagementPermission.ts
  • hooks/useWaveCurationDrops.ts
  • openapi.yaml
  • package.json
  • services/api/drop-curations-api.ts

Comment on lines +331 to +334
async function confirmClearProfileWave() {
await clearSelectedProfileWave();
setIsClearConfirmOpen(false);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Modal may close prematurely on persistence failure.

confirmClearProfileWave closes the modal immediately after await clearSelectedProfileWave(), but if the operation fails, the user won't see the error in context since the modal is already closed. Consider only closing on success.

🛠️ Proposed fix
   async function confirmClearProfileWave() {
-    await clearSelectedProfileWave();
-    setIsClearConfirmOpen(false);
+    try {
+      await clearSelectedProfileWave();
+      setIsClearConfirmOpen(false);
+    } catch {
+      // Keep modal open on failure; toast will show 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
async function confirmClearProfileWave() {
await clearSelectedProfileWave();
setIsClearConfirmOpen(false);
}
async function confirmClearProfileWave() {
try {
await clearSelectedProfileWave();
setIsClearConfirmOpen(false);
} catch {
// Keep modal open on failure; toast will show error
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/user/waves/UserPageProfileWave.tsx` around lines 331 - 334,
confirmClearProfileWave currently awaits clearSelectedProfileWave() then
unconditionally calls setIsClearConfirmOpen(false), which will close the modal
even if persistence fails; change confirmClearProfileWave to only close the
modal on success by wrapping the await in a try/catch: call await
clearSelectedProfileWave() inside try, then call setIsClearConfirmOpen(false)
after a successful await, and handle errors in catch (e.g., surface the error
via existing error handler/UI instead of closing the modal). Ensure you
reference confirmClearProfileWave, clearSelectedProfileWave, and
setIsClearConfirmOpen when making the change.

Comment on lines +550 to +553
async function confirmUnavailableClearProfileWave() {
await clearSelectedProfileWave();
}, [clearSelectedProfileWave]);
setIsUnavailableClearConfirmOpen(false);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Same modal close behavior issue.

Same as confirmClearProfileWave - consider keeping the modal open on failure so the user sees the error in context.

🛠️ Proposed fix
   async function confirmUnavailableClearProfileWave() {
-    await clearSelectedProfileWave();
-    setIsUnavailableClearConfirmOpen(false);
+    try {
+      await clearSelectedProfileWave();
+      setIsUnavailableClearConfirmOpen(false);
+    } catch {
+      // Keep modal open on failure; toast will show 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
async function confirmUnavailableClearProfileWave() {
await clearSelectedProfileWave();
}, [clearSelectedProfileWave]);
setIsUnavailableClearConfirmOpen(false);
}
async function confirmUnavailableClearProfileWave() {
try {
await clearSelectedProfileWave();
setIsUnavailableClearConfirmOpen(false);
} catch {
// Keep modal open on failure; toast will show error
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/user/waves/UserPageProfileWave.tsx` around lines 550 - 553, The
confirmUnavailableClearProfileWave function currently awaits
clearSelectedProfileWave() and then unconditionally closes the modal via
setIsUnavailableClearConfirmOpen(false); wrap the await in a try/catch and only
call setIsUnavailableClearConfirmOpen(false) when clearSelectedProfileWave
resolves successfully, leaving the modal open on error so the user can see the
failure (mirror the behavior needed for confirmClearProfileWave); surface or
rethrow the caught error so existing error UI/notifications can display it.

Comment thread hooks/drops/useDropCurationOrderMutation.ts Outdated
Comment thread openapi.yaml
Comment on lines +977 to +992
- name: min_serial_no
in: query
required: false
description: Oldest message if null
schema:
type: integer
format: int64
minimum: 1
- name: older_first
in: query
required: false
description: >-
By default this endpoint orders things newer first, but if you set
it to true then it starts from older drops.
schema:
type: boolean
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
python - <<'PY'
from collections import Counter

names = []
for i, line in enumerate(open("openapi.yaml"), start=1):
    if 955 <= i <= 999 and line.lstrip().startswith("- name:"):
        names.append((i, line.split(":", 1)[1].strip()))

print("parameters:", names)
counts = Counter(name for _, name in names)
print("duplicates:", {k: v for k, v in counts.items() if v > 1})
PY

Repository: 6529-Collections/6529seize-frontend

Length of output: 276


🏁 Script executed:

# Check the operation context and structure around lines 955-1000
sed -n '945,1000p' openapi.yaml | cat -n

Repository: 6529-Collections/6529seize-frontend

Length of output: 2079


Remove the duplicated min_serial_no and older_first query parameters from GET /light-drops.

The operation declares both parameters twice (at lines 963–976 and 977–992). OpenAPI requires parameters to be unique by (name, in) within an operation; duplicates break spec validation and client generation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openapi.yaml` around lines 977 - 992, The GET /light-drops operation
currently defines the query parameters min_serial_no and older_first twice;
remove the duplicated parameter definitions so each (name, in) pair appears only
once in the operation. Keep the canonical definitions for min_serial_no (type
integer, format int64, minimum 1) and older_first (type boolean) and, if the two
blocks differ, merge any unique description text into the remaining single
definitions for min_serial_no and older_first to preserve intent.

Comment on lines +6 to +7
const getDropCurationEndpoint = (dropId: string): string =>
`${publicEnv.API_ENDPOINT}/api/drops/${dropId}/curations`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Encode dropId before inserting it into the path.

dropId is used as a raw path segment in both requests. If it ever contains /, ?, or #, the client will hit the wrong endpoint.

Suggested fix
 const getDropCurationEndpoint = (dropId: string): string =>
-  `${publicEnv.API_ENDPOINT}/api/drops/${dropId}/curations`;
+  `${publicEnv.API_ENDPOINT}/api/drops/${encodeURIComponent(dropId)}/curations`;

 export const deleteDropCuration = async ({
   dropId,
   body,
 }: {
   readonly dropId: string;
   readonly body: ApiDropCurationRequest;
 }): Promise<void> => {
   await commonApiDeleteWithBody<ApiDropCurationRequest, void>({
-    endpoint: `drops/${dropId}/curations`,
+    endpoint: `drops/${encodeURIComponent(dropId)}/curations`,
     body,
   });
 };

Also applies to: 75-75

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/api/drop-curations-api.ts` around lines 6 - 7, The
getDropCurationEndpoint helper inserts dropId directly into the URL path which
can break if dropId contains reserved characters; update getDropCurationEndpoint
(and any other uses around the other occurrence) to encode the path segment by
applying encodeURIComponent to dropId before concatenation so the generated
endpoint is safe when dropId contains "/", "?", "#", etc.

Signed-off-by: ragnep <ragneinfo@gmail.com>
@sonarqubecloud
Copy link
Copy Markdown

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