Skip to content

fix: reload table after archive/unarchive rows#938

Open
tomrndom wants to merge 8 commits into
masterfrom
fix/reload-table-on-archive
Open

fix: reload table after archive/unarchive rows#938
tomrndom wants to merge 8 commits into
masterfrom
fix/reload-table-on-archive

Conversation

@tomrndom

@tomrndom tomrndom commented May 14, 2026

Copy link
Copy Markdown

ref: https://app.clickup.com/t/86b7v230m

Signed-off-by: Tomás Castillo tcastilloboireau@gmail.com

Summary by CodeRabbit

  • Bug Fixes

    • Enhanced pagination handling when archiving or unarchiving items across form templates, page templates, inventory lists, and sponsor pages to automatically navigate to the nearest valid page instead of potentially displaying empty pages.
  • Tests

    • Added comprehensive test coverage for pagination adjustments following item archive/unarchive actions.

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR implements safe pagination across item archive/unarchive operations. A new utility function computes valid page indices after item removal, and is integrated into 9 list-page archive handlers across global sponsors and sponsor-scoped sections. Reducers and tests are updated to track total count changes and validate the new behavior.

Changes

Safe Pagination After Archive/Unarchive

Layer / File(s) Summary
Safe page calculation utility
src/utils/methods.js
Adds getSafePageAfterRemove(totalCount, perPage, currentPage) to compute the last valid page after one-item removal, clamped to a minimum of 1.
Global sponsors list archive/unarchive handlers
src/pages/sponsors-global/form-templates/form-template-item-list-page.js, form-template-list-page.js, inventory/inventory-list-page.js, page-templates/page-template-list-page.js
Updates archive/unarchive handlers in 4 global list pages to import getSafePageAfterRemove and reload lists using a computed safePage on success; falls back to currentPage on error.
Sponsor pages and tabs archive/unarchive handlers
src/pages/sponsors/show-pages-list-page/index.js, sponsor-forms-list-page/index.js, sponsor-form-item-list-page/index.js, sponsor-page/tabs/sponsor-forms-tab/index.js, sponsor-page/tabs/sponsor-forms-tab/components/manage-items/sponsor-forms-manage-items.js, sponsor-page/tabs/sponsor-pages-tab/index.js
Updates archive/unarchive handlers across 6 sponsor-scoped pages and tabs to import getSafePageAfterRemove and refetch using safePage while preserving existing sort, filter, and pagination parameters.
Reducer total count updates
src/reducers/sponsors_inventory/inventory-item-list-reducer.js, form-template-item-list-reducer.js, form-template-list-reducer.js, page-template-list-reducer.js
Inventory item reducer now decrements totalInventoryItems on archive/unarchive; form template and page template reducers reformat return statements while maintaining existing total-count behavior.
Updated tests
src/utils/__tests__/methods.test.js, src/reducers/sponsors/__tests__/sponsor-form-items-list-reducer.test.js
Methods test suite adds comprehensive coverage for getSafePageAfterRemove with assertions for page clamping and adjustment after removal; sponsor form item reducer test expectations updated to expect totalCount decrements.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • fntechgit/summit-admin#809: Earlier PR that added the initial archive/unarchive dispatch and re-fetch in sponsor-pages-tab/index.js; this PR enhances that flow with pagination-safe page selection via getSafePageAfterRemove.

Suggested reviewers

  • smarcet
  • martinquiroga-exo

🐰 A rabbit hops through list pages with glee,
Each archive brings safe pagination, you see!
No empty pages left to roam,
The safePage brings items back home, 🏠
Math.ceil makes sure we're never at sea!

🚥 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 The title 'fix: reload table after archive/unarchive rows' is specific and directly relates to the main change—improving pagination handling when items are archived/unarchived by reloading tables with safe page indices.
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.

✏️ 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 fix/reload-table-on-archive

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

@tomrndom tomrndom requested a review from smarcet May 14, 2026 20:49
Comment thread src/utils/methods.js

@smarcet smarcet 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.

@tomrndom please review comments

Comment thread src/pages/sponsors-global/form-templates/form-template-list-page.js
@smarcet

smarcet commented May 15, 2026

Copy link
Copy Markdown

[HIGH] totalCount fed into getSafePageAfterRemove is stale — reducers never update it on archive/unarchive

Note: the reducers are not modified by this PR, so this is a pre-existing structural issue that this PR inherits. Flagging here because the correctness of getSafePageAfterRemove depends on totalCount being accurate.

What the reducers do today:

All FORM_TEMPLATE_ARCHIVED, FORM_TEMPLATE_UNARCHIVED, SPONSOR_CUSTOMIZED_FORM_ARCHIVED_CHANGED, etc. handlers only toggle is_archived on the matching item in the list. They do not decrement totalCount. Example from form-template-list-reducer.js:

case FORM_TEMPLATE_ARCHIVED: {
  const updatedFormTemplates = state.formTemplates.map((item) =>
    item.id === updatedFormTemplate.id ? { ...item, is_archived: true } : item
  );
  return { ...state, formTemplates: updatedFormTemplates };
  // ↑ totalFormTemplates is untouched
}

Compare with FORM_TEMPLATE_DELETED, which correctly decrements:

case FORM_TEMPLATE_DELETED:
  return { ...state, formTemplates: [...], totalFormTemplates: state.totalFormTemplates - 1 };

Why this matters for this PR:

getSafePageAfterRemove(totalFormTemplates, perPage, currentPage) reads totalFormTemplates from Redux — which is the count from the last RECEIVE response. So:

  1. User is on page 3, totalCount = 21, perPage = 10. Archives item A → safe page calculated correctly from 21 → reloads, totalCount becomes 20.
  2. Without a full reload completing first (rapid clicks), user archives item B → getSafePageAfterRemove still reads totalCount = 21 (the ARCHIVED action never decremented it) → safe page is off by one.

Under normal single-click usage this is masked by the follow-up getItems refreshing totalCount from the server. But it is a latent race: if the user archives two items faster than the first reload completes, the second page calculation is wrong.

Correct fix: decrement totalCount in each ARCHIVED reducer case (mirroring what DELETED already does), so the in-flight page calculation always uses the post-action count:

case FORM_TEMPLATE_ARCHIVED: {
  const updatedFormTemplates = state.formTemplates.map((item) =>
    item.id === updatedFormTemplate.id ? { ...item, is_archived: true } : item
  );
  return {
    ...state,
    formTemplates: updatedFormTemplates,
    totalFormTemplates: state.totalFormTemplates - 1  // ← add this
  };
}

This applies to all domains: form-template-list-reducer, inventory-list-reducer, show-pages-list-reducer, sponsor-forms-list-reducer, and sponsor-page-forms-list-reducer.


This finding is secondary to the direction×filter bug already commented on getSafePageAfterRemove — fix that one first.

@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 (1)
src/reducers/sponsors/__tests__/sponsor-form-items-list-reducer.test.js (1)

311-311: ⚡ Quick win

Add a regression test for no-op archive/unarchive count behavior.

Good update on expected decrements; please also add a case where the target item is missing or already in the target state and assert totalCount does not change.

Also applies to: 380-380

🤖 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 `@src/reducers/sponsors/__tests__/sponsor-form-items-list-reducer.test.js` at
line 311, Add regression tests to assert totalCount is unchanged when
archive/unarchive is a no-op: in the sponsor-form-items-list-reducer test suite
add two cases calling the reducer (via the same action creators used elsewhere
in the file) where the target item is either missing or already in the target
state (already archived when archiving, already unarchived when unarchiving) and
assert that sponsorFormItemsListReducer returns state with the same totalCount
value as the input; reuse the existing test helpers/setup and the same action
types used around the existing totalCount decrement tests so the new cases
mirror those scenarios but expect no change.
🤖 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 `@src/reducers/sponsors_inventory/form-template-item-list-reducer.js`:
- Around line 109-113: The reducer is unconditionally decrementing
totalFormTemplateItems when returning the new state, which causes undercounts on
no-op archive/unarchive actions; update the logic in the form-template-item-list
reducer (the code that builds updatedFormTemplatesItems and sets
totalFormTemplateItems) to detect whether the target item's archived state
actually changed (compare the previous item's archived flag to the new value on
the item in updatedFormTemplatesItems) and only decrement/increment
totalFormTemplateItems when a real transition occurred, leaving
totalFormTemplateItems unchanged for no-op/replayed actions.

In `@src/reducers/sponsors_inventory/form-template-list-reducer.js`:
- Around line 108-112: The reducer currently decrements totalFormTemplates
unconditionally when returning the new state; change it to only decrement when
the template was actually removed from the current set by comparing lengths (or
checking existence) of updatedFormTemplates versus state.formTemplates or by
verifying the removed id from action.payload existed; update the return so
totalFormTemplates = state.totalFormTemplates - 1 only if removal occurred,
otherwise leave totalFormTemplates unchanged (apply the same guard for both
occurrences where totalFormTemplates is decremented).

In `@src/reducers/sponsors_inventory/inventory-item-list-reducer.js`:
- Around line 204-208: The reducer currently unconditionally decrements
totalInventoryItems by 1 (at the return that spreads state and sets
inventoryItems: updatedInventoryItems and totalInventoryItems:
state.totalInventoryItems - 1), which can desync counts on no-ops or duplicate
actions; change it to compute the actual change (e.g., const delta =
state.inventoryItems.length - updatedInventoryItems.length or check whether the
removed item was found) and set totalInventoryItems: Math.max(0,
state.totalInventoryItems - delta) or directly set totalInventoryItems:
updatedInventoryItems.length; apply the same conditional update logic to the
other similar return (lines around the second occurrence using
updatedInventoryItems) so totals only change when inventoryItems length actually
changes.

In `@src/reducers/sponsors_inventory/page-template-list-reducer.js`:
- Around line 112-116: The reducer is unconditionally decrementing
totalPageTemplates which undercounts when no row actually changed; instead
compute how many items were removed/changed by comparing state.pageTemplates and
updatedPageTemplates (e.g., removedCount = state.pageTemplates.length -
updatedPageTemplates.length or detect the specific id change) and subtract only
that removedCount from totalPageTemplates (or leave it unchanged if removedCount
is 0); update the return that currently sets totalPageTemplates:
state.totalPageTemplates - 1 to use the computed removedCount (and apply the
same guard in the other similar block that updates totalPageTemplates).

In `@src/reducers/sponsors/show-pages-list-reducer.js`:
- Around line 116-117: The reducer updates totalCount by subtracting 1 which can
go negative; change the assignment(s) that set totalCount (the object returned
in the reducer around the lines updating totalCount, e.g., where totalCount:
state.totalCount - 1 is used) to clamp the result to a minimum of 0 (use
Math.max(0, state.totalCount - 1) or equivalent) and apply the same fix to the
other occurrence mentioned (the second totalCount update at lines ~127-128).

In `@src/reducers/sponsors/sponsor-page-pages-list-reducer.js`:
- Around line 243-244: When removing a page you currently always decrement
state.customizedPages.totalItems; change the reducer logic so totalItems is only
decremented when a page was actually removed. Concretely, compute the new pages
array (e.g., newPages = pages.filter(...)) and compare lengths (or check a found
flag) — if newPages.length < pages.length then set totalItems =
state.customizedPages.totalItems - 1 (clamped to >= 0); otherwise leave
totalItems unchanged. Apply this change to both places that update pages and
totalItems (the blocks that build pages and set totalItems currently using
pages: [...pages], totalItems: state.customizedPages.totalItems - 1) so
duplicate/out-of-order actions do not drift the count.

---

Nitpick comments:
In `@src/reducers/sponsors/__tests__/sponsor-form-items-list-reducer.test.js`:
- Line 311: Add regression tests to assert totalCount is unchanged when
archive/unarchive is a no-op: in the sponsor-form-items-list-reducer test suite
add two cases calling the reducer (via the same action creators used elsewhere
in the file) where the target item is either missing or already in the target
state (already archived when archiving, already unarchived when unarchiving) and
assert that sponsorFormItemsListReducer returns state with the same totalCount
value as the input; reuse the existing test helpers/setup and the same action
types used around the existing totalCount decrement tests so the new cases
mirror those scenarios but expect no change.
🪄 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: 761db084-fe43-4aab-b9a6-d7df7025054a

📥 Commits

Reviewing files that changed from the base of the PR and between 9484135 and f10d869.

📒 Files selected for processing (21)
  • src/pages/sponsors-global/form-templates/form-template-item-list-page.js
  • src/pages/sponsors-global/form-templates/form-template-list-page.js
  • src/pages/sponsors-global/inventory/inventory-list-page.js
  • src/pages/sponsors-global/page-templates/page-template-list-page.js
  • src/pages/sponsors/show-pages-list-page/index.js
  • src/pages/sponsors/sponsor-form-item-list-page/index.js
  • src/pages/sponsors/sponsor-forms-list-page/index.js
  • src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/manage-items/sponsor-forms-manage-items.js
  • src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/index.js
  • src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/index.js
  • src/reducers/sponsors/__tests__/sponsor-form-items-list-reducer.test.js
  • src/reducers/sponsors/show-pages-list-reducer.js
  • src/reducers/sponsors/sponsor-customized-form-items-list-reducer.js
  • src/reducers/sponsors/sponsor-form-items-list-reducer.js
  • src/reducers/sponsors/sponsor-forms-list-reducer.js
  • src/reducers/sponsors/sponsor-page-forms-list-reducer.js
  • src/reducers/sponsors/sponsor-page-pages-list-reducer.js
  • src/reducers/sponsors_inventory/form-template-item-list-reducer.js
  • src/reducers/sponsors_inventory/form-template-list-reducer.js
  • src/reducers/sponsors_inventory/inventory-item-list-reducer.js
  • src/reducers/sponsors_inventory/page-template-list-reducer.js
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/index.js
  • src/pages/sponsors/sponsor-form-item-list-page/index.js
  • src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/index.js
  • src/pages/sponsors-global/form-templates/form-template-item-list-page.js
  • src/pages/sponsors/show-pages-list-page/index.js
  • src/pages/sponsors/sponsor-forms-list-page/index.js
  • src/pages/sponsors-global/page-templates/page-template-list-page.js

Comment thread src/reducers/sponsors_inventory/form-template-list-reducer.js
Comment thread src/reducers/sponsors_inventory/inventory-item-list-reducer.js
Comment thread src/reducers/sponsors_inventory/page-template-list-reducer.js
Comment thread src/reducers/sponsors/show-pages-list-reducer.js Outdated
Comment thread src/reducers/sponsors/sponsor-page-pages-list-reducer.js Outdated
Comment thread src/utils/methods.js

@smarcet smarcet 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.

@tomrndom please review comment
#938 (comment)

@tomrndom tomrndom force-pushed the fix/reload-table-on-archive branch from cd7b812 to b8545c5 Compare May 20, 2026 20:11

@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 (4)
src/reducers/sponsors/sponsor-page-forms-list-reducer.js (1)

234-252: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid unconditional decrement in SPONSOR_CUSTOMIZED_FORM_ARCHIVED_CHANGED.

Line 251 should decrement only if the targeted form actually changes is_archived.

Proposed fix
     case SPONSOR_CUSTOMIZED_FORM_ARCHIVED_CHANGED: {
       const { formId, isArchived } = payload;
+      const shouldDecrement = state.customizedForms.forms.some(
+        (form) => form.id === formId && form.is_archived !== isArchived
+      );
       const forms = state.customizedForms.forms.map((form) => {
         if (form.id === formId) {
           return {
             ...form,
             is_archived: isArchived
           };
         }
         return form;
       });

       return {
         ...state,
         customizedForms: {
           ...state.customizedForms,
           forms,
-          totalCount: state.customizedForms.totalCount - 1
+          totalCount: shouldDecrement
+            ? Math.max(0, state.customizedForms.totalCount - 1)
+            : state.customizedForms.totalCount
         }
       };
     }
🤖 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 `@src/reducers/sponsors/sponsor-page-forms-list-reducer.js` around lines 234 -
252, The reducer handling SPONSOR_CUSTOMIZED_FORM_ARCHIVED_CHANGED
unconditionally subtracts 1 from state.customizedForms.totalCount; change it to
first detect whether the matched form's is_archived actually changes by locating
the form with form.id === formId (use the existing map or a prior find), compare
its current is_archived to payload.isArchived, and only decrement totalCount
when the value changed and payload.isArchived is true (leave totalCount
unchanged otherwise); update the return to use this conditional delta when
constructing customizedForms.totalCount.
src/reducers/sponsors/sponsor-form-items-list-reducer.js (1)

118-135: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Prevent totalCount drift on no-op archive/unarchive actions.

Line 125 and Line 134 always decrement. If the item is absent or already in target state, pagination totals become inconsistent.

Proposed fix
     case SPONSOR_FORM_ITEM_ARCHIVED: {
       const { id: itemId } = payload.response;
+      const shouldDecrement = state.items.some(
+        (item) => item.id === itemId && item.is_archived !== true
+      );

       const items = state.items.map((item) =>
         item.id === itemId ? { ...item, is_archived: true } : item
       );

-      return { ...state, items, totalCount: state.totalCount - 1 };
+      return {
+        ...state,
+        items,
+        totalCount: shouldDecrement
+          ? Math.max(0, state.totalCount - 1)
+          : state.totalCount
+      };
     }
     case SPONSOR_FORM_ITEM_UNARCHIVED: {
       const { itemId } = payload;
+      const shouldDecrement = state.items.some(
+        (item) => item.id === itemId && item.is_archived !== false
+      );

       const items = state.items.map((item) =>
         item.id === itemId ? { ...item, is_archived: false } : item
       );

-      return { ...state, items, totalCount: state.totalCount - 1 };
+      return {
+        ...state,
+        items,
+        totalCount: shouldDecrement
+          ? Math.max(0, state.totalCount - 1)
+          : state.totalCount
+      };
     }
🤖 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 `@src/reducers/sponsors/sponsor-form-items-list-reducer.js` around lines 118 -
135, In the SPONSOR_FORM_ITEM_ARCHIVED and SPONSOR_FORM_ITEM_UNARCHIVED reducer
cases, avoid blindly changing totalCount — determine whether an item was
actually found and its archived state changed before adjusting totals: for
SPONSOR_FORM_ITEM_ARCHIVED (use payload.response.id) map state.items and detect
if an item with that id existed and its is_archived transitioned from false to
true, then decrement totalCount by 1 only in that case; for
SPONSOR_FORM_ITEM_UNARCHIVED (use payload.itemId) map state.items and detect if
an item existed and its is_archived transitioned from true to false, then
increment totalCount by 1 only in that case; if no item is found or no state
change occurred leave totalCount unchanged.
src/reducers/sponsors/sponsor-forms-list-reducer.js (1)

151-168: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Make totalCount updates conditional on actual state change.

Line 158 and Line 167 should only decrement when the matched form actually transitions archive state.

Proposed fix
     case SPONSOR_FORM_ARCHIVED: {
       const { id: formId } = payload.response;
+      const shouldDecrement = state.sponsorForms.some(
+        (item) => item.id === formId && item.is_archived !== true
+      );

       const sponsorForms = state.sponsorForms.map((item) =>
         item.id === formId ? { ...item, is_archived: true } : item
       );

-      return { ...state, sponsorForms, totalCount: state.totalCount - 1 };
+      return {
+        ...state,
+        sponsorForms,
+        totalCount: shouldDecrement
+          ? Math.max(0, state.totalCount - 1)
+          : state.totalCount
+      };
     }
     case SPONSOR_FORM_UNARCHIVED: {
       const { formId } = payload;
+      const shouldDecrement = state.sponsorForms.some(
+        (item) => item.id === formId && item.is_archived !== false
+      );

       const sponsorForms = state.sponsorForms.map((item) =>
         item.id === formId ? { ...item, is_archived: false } : item
       );

-      return { ...state, sponsorForms, totalCount: state.totalCount - 1 };
+      return {
+        ...state,
+        sponsorForms,
+        totalCount: shouldDecrement
+          ? Math.max(0, state.totalCount - 1)
+          : state.totalCount
+      };
     }
🤖 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 `@src/reducers/sponsors/sponsor-forms-list-reducer.js` around lines 151 - 168,
The reducer currently always adjusts totalCount when handling
SPONSOR_FORM_ARCHIVED and SPONSOR_FORM_UNARCHIVED; change both branches to only
mutate totalCount when the matched form actually changes archive state: for
SPONSOR_FORM_ARCHIVED (use payload.response.id as formId) find the item in
state.sponsorForms, if item.exists and item.is_archived is false then set
is_archived: true and decrement totalCount by 1, otherwise leave totalCount
unchanged; for SPONSOR_FORM_UNARCHIVED (use payload.formId) similarly only set
is_archived: false and increment totalCount by 1 if the item was previously
archived, otherwise keep totalCount as-is; return the updated sponsorForms array
and the conditionally updated totalCount.
src/reducers/sponsors/sponsor-customized-form-items-list-reducer.js (1)

123-140: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard totalCount decrement to real archive-state transitions only.

Line 130 and Line 139 decrement unconditionally. If the target row is missing/already in target state, totalCount drifts.

Proposed fix
     case SPONSOR_CUSTOMIZED_FORM_ITEM_ARCHIVED: {
       const { id: itemId } = payload.response;
+      const shouldDecrement = state.items.some(
+        (item) => item.id === itemId && item.is_archived !== true
+      );

       const items = state.items.map((item) =>
         item.id === itemId ? { ...item, is_archived: true } : item
       );

-      return { ...state, items, totalCount: state.totalCount - 1 };
+      return {
+        ...state,
+        items,
+        totalCount: shouldDecrement
+          ? Math.max(0, state.totalCount - 1)
+          : state.totalCount
+      };
     }
     case SPONSOR_CUSTOMIZED_FORM_ITEM_UNARCHIVED: {
       const { itemId } = payload;
+      const shouldDecrement = state.items.some(
+        (item) => item.id === itemId && item.is_archived !== false
+      );

       const items = state.items.map((item) =>
         item.id === itemId ? { ...item, is_archived: false } : item
       );

-      return { ...state, items, totalCount: state.totalCount - 1 };
+      return {
+        ...state,
+        items,
+        totalCount: shouldDecrement
+          ? Math.max(0, state.totalCount - 1)
+          : state.totalCount
+      };
     }
🤖 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 `@src/reducers/sponsors/sponsor-customized-form-items-list-reducer.js` around
lines 123 - 140, The SPONSOR_CUSTOMIZED_FORM_ITEM_ARCHIVED and
SPONSOR_CUSTOMIZED_FORM_ITEM_UNARCHIVED cases unconditionally change totalCount;
instead, first locate the target item from state.items (use payload.response.id
for ARCHIVED and payload.itemId for UNARCHIVED), check its current is_archived
flag, and only modify totalCount when the flag actually flips: for ARCHIVED, set
is_archived true and decrement totalCount by 1 only if the item existed and was
previously false; for UNARCHIVED, set is_archived false and increment totalCount
by 1 only if the item existed and was previously true; return updated items and
the conditionally adjusted totalCount.
🤖 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
`@src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/manage-items/sponsor-forms-manage-items.js`:
- Around line 154-185: The handler handleArchiveItem currently uses
getSafePageAfterRemove for both archive and unarchive flows; change it so
getSafePageAfterRemove(...) is used only when performing a removal
(archiveSponsorCustomizedFormItem) and for the unarchive path call
getSponsorCustomizedFormItems with the existing currentPage (no safe-page
adjustment), keeping the catch behavior consistent by reloading the appropriate
page for the attempted action; update calls around
archiveSponsorCustomizedFormItem(formId, item.id) and
unarchiveSponsorCustomizedFormItem(formId, item.id) to branch the then() logic
so the page argument passed to getSponsorCustomizedFormItems is safePage only
for archive and currentPage for unarchive.

---

Outside diff comments:
In `@src/reducers/sponsors/sponsor-customized-form-items-list-reducer.js`:
- Around line 123-140: The SPONSOR_CUSTOMIZED_FORM_ITEM_ARCHIVED and
SPONSOR_CUSTOMIZED_FORM_ITEM_UNARCHIVED cases unconditionally change totalCount;
instead, first locate the target item from state.items (use payload.response.id
for ARCHIVED and payload.itemId for UNARCHIVED), check its current is_archived
flag, and only modify totalCount when the flag actually flips: for ARCHIVED, set
is_archived true and decrement totalCount by 1 only if the item existed and was
previously false; for UNARCHIVED, set is_archived false and increment totalCount
by 1 only if the item existed and was previously true; return updated items and
the conditionally adjusted totalCount.

In `@src/reducers/sponsors/sponsor-form-items-list-reducer.js`:
- Around line 118-135: In the SPONSOR_FORM_ITEM_ARCHIVED and
SPONSOR_FORM_ITEM_UNARCHIVED reducer cases, avoid blindly changing totalCount —
determine whether an item was actually found and its archived state changed
before adjusting totals: for SPONSOR_FORM_ITEM_ARCHIVED (use
payload.response.id) map state.items and detect if an item with that id existed
and its is_archived transitioned from false to true, then decrement totalCount
by 1 only in that case; for SPONSOR_FORM_ITEM_UNARCHIVED (use payload.itemId)
map state.items and detect if an item existed and its is_archived transitioned
from true to false, then increment totalCount by 1 only in that case; if no item
is found or no state change occurred leave totalCount unchanged.

In `@src/reducers/sponsors/sponsor-forms-list-reducer.js`:
- Around line 151-168: The reducer currently always adjusts totalCount when
handling SPONSOR_FORM_ARCHIVED and SPONSOR_FORM_UNARCHIVED; change both branches
to only mutate totalCount when the matched form actually changes archive state:
for SPONSOR_FORM_ARCHIVED (use payload.response.id as formId) find the item in
state.sponsorForms, if item.exists and item.is_archived is false then set
is_archived: true and decrement totalCount by 1, otherwise leave totalCount
unchanged; for SPONSOR_FORM_UNARCHIVED (use payload.formId) similarly only set
is_archived: false and increment totalCount by 1 if the item was previously
archived, otherwise keep totalCount as-is; return the updated sponsorForms array
and the conditionally updated totalCount.

In `@src/reducers/sponsors/sponsor-page-forms-list-reducer.js`:
- Around line 234-252: The reducer handling
SPONSOR_CUSTOMIZED_FORM_ARCHIVED_CHANGED unconditionally subtracts 1 from
state.customizedForms.totalCount; change it to first detect whether the matched
form's is_archived actually changes by locating the form with form.id === formId
(use the existing map or a prior find), compare its current is_archived to
payload.isArchived, and only decrement totalCount when the value changed and
payload.isArchived is true (leave totalCount unchanged otherwise); update the
return to use this conditional delta when constructing
customizedForms.totalCount.
🪄 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: f5ea9f81-7c69-43d0-b4fc-710abd128e57

📥 Commits

Reviewing files that changed from the base of the PR and between cd7b812 and b8545c5.

📒 Files selected for processing (23)
  • src/pages/sponsors-global/form-templates/form-template-item-list-page.js
  • src/pages/sponsors-global/form-templates/form-template-list-page.js
  • src/pages/sponsors-global/inventory/inventory-list-page.js
  • src/pages/sponsors-global/page-templates/page-template-list-page.js
  • src/pages/sponsors/show-pages-list-page/index.js
  • src/pages/sponsors/sponsor-form-item-list-page/index.js
  • src/pages/sponsors/sponsor-forms-list-page/index.js
  • src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/manage-items/sponsor-forms-manage-items.js
  • src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/index.js
  • src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/index.js
  • src/reducers/sponsors/__tests__/sponsor-form-items-list-reducer.test.js
  • src/reducers/sponsors/show-pages-list-reducer.js
  • src/reducers/sponsors/sponsor-customized-form-items-list-reducer.js
  • src/reducers/sponsors/sponsor-form-items-list-reducer.js
  • src/reducers/sponsors/sponsor-forms-list-reducer.js
  • src/reducers/sponsors/sponsor-page-forms-list-reducer.js
  • src/reducers/sponsors/sponsor-page-pages-list-reducer.js
  • src/reducers/sponsors_inventory/form-template-item-list-reducer.js
  • src/reducers/sponsors_inventory/form-template-list-reducer.js
  • src/reducers/sponsors_inventory/inventory-item-list-reducer.js
  • src/reducers/sponsors_inventory/page-template-list-reducer.js
  • src/utils/__tests__/methods.test.js
  • src/utils/methods.js

@tomrndom tomrndom requested a review from smarcet May 20, 2026 20:37
@smarcet smarcet requested a review from santipalenque May 22, 2026 02:52

@santipalenque santipalenque 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.

@tomrndom I think there is a much easier way of achieving this. When user archives a template, you whould check in the reducer if the "Show archived " is false , this means there is a chance the user is archiving the only item in the current page, so we need to refresh to the previous page. So if "Show archived" is false AND totalCount/perPage is an integer AND currentPage is not 1, then we change currentPage -1 . You can do all this in the archiveItem reducer action, and then just call getFormTemplateItems normally here archiveFormTemplateItem in the actions file

@smarcet smarcet 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.

Review focusing on the open threads from @smarcet (Thread 1) and @santipalenque (Thread 11), plus two correctness findings in the implementation.

Comment thread src/pages/sponsors-global/form-templates/form-template-item-list-page.js Outdated
Comment thread src/reducers/sponsors_inventory/form-template-item-list-reducer.js Outdated
Comment thread src/reducers/sponsors/show-pages-list-reducer.js Outdated
Comment thread src/utils/methods.js
@smarcet smarcet requested review from santipalenque and smarcet June 11, 2026 18:13
tomrndom added 4 commits June 11, 2026 16:00
Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
@tomrndom tomrndom force-pushed the fix/reload-table-on-archive branch from b8545c5 to 62a4588 Compare June 11, 2026 19:00
tomrndom added 2 commits June 11, 2026 16:15
… the page reload

Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>

@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

🤖 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 `@src/reducers/sponsors_inventory/form-template-item-list-reducer.js`:
- Around line 111-114: When toggling an item's is_archived in the reducer,
update totalFormTemplateItems only when the archive state actually changes: find
the previous item (by id) in state.formTemplateItems, compare its is_archived to
the new value in updatedFormTemplatesItems, and if it changed from false->true
decrement totalFormTemplateItems with Math.max(0, state.totalFormTemplateItems -
1); if it changed from true->false increment totalFormTemplateItems by 1. Apply
this logic in both places that build updatedFormTemplatesItems (the blocks
around the current is_archived toggles) so duplicate/replayed dispatches won't
drive totals negative or leave totals stale.
🪄 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: d3e4cbf3-c9f3-4edc-a8c4-bcc3727f7e0f

📥 Commits

Reviewing files that changed from the base of the PR and between b8545c5 and de46eb2.

📒 Files selected for processing (17)
  • src/pages/sponsors-global/form-templates/form-template-item-list-page.js
  • src/pages/sponsors-global/form-templates/form-template-list-page.js
  • src/pages/sponsors-global/inventory/inventory-list-page.js
  • src/pages/sponsors-global/page-templates/page-template-list-page.js
  • src/pages/sponsors/show-pages-list-page/index.js
  • src/pages/sponsors/sponsor-form-item-list-page/index.js
  • src/pages/sponsors/sponsor-forms-list-page/index.js
  • src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/manage-items/sponsor-forms-manage-items.js
  • src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/index.js
  • src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/index.js
  • src/reducers/sponsors/__tests__/sponsor-form-items-list-reducer.test.js
  • src/reducers/sponsors_inventory/form-template-item-list-reducer.js
  • src/reducers/sponsors_inventory/form-template-list-reducer.js
  • src/reducers/sponsors_inventory/inventory-item-list-reducer.js
  • src/reducers/sponsors_inventory/page-template-list-reducer.js
  • src/utils/__tests__/methods.test.js
  • src/utils/methods.js
✅ Files skipped from review due to trivial changes (3)
  • src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/manage-items/sponsor-forms-manage-items.js
  • src/reducers/sponsors_inventory/form-template-list-reducer.js
  • src/reducers/sponsors_inventory/page-template-list-reducer.js
🚧 Files skipped from review as they are similar to previous changes (12)
  • src/utils/methods.js
  • src/pages/sponsors-global/form-templates/form-template-list-page.js
  • src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/index.js
  • src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/index.js
  • src/utils/tests/methods.test.js
  • src/pages/sponsors-global/page-templates/page-template-list-page.js
  • src/pages/sponsors/sponsor-forms-list-page/index.js
  • src/pages/sponsors/show-pages-list-page/index.js
  • src/pages/sponsors-global/form-templates/form-template-item-list-page.js
  • src/pages/sponsors-global/inventory/inventory-list-page.js
  • src/reducers/sponsors_inventory/inventory-item-list-reducer.js
  • src/pages/sponsors/sponsor-form-item-list-page/index.js

Comment thread src/reducers/sponsors_inventory/form-template-item-list-reducer.js
… reducers

Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>

@santipalenque santipalenque 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.

Seems that you have unnecessary changes @tomrndom

Comment thread src/pages/sponsors-global/form-templates/form-template-item-list-page.js Outdated
Comment thread src/pages/sponsors-global/form-templates/form-template-list-page.js Outdated
Comment thread src/pages/sponsors-global/inventory/inventory-list-page.js Outdated
Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
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.

3 participants