Skip to content

Comments

feat: add sponsor pages tab, add customized and managed tables#771

Open
tomrndom wants to merge 4 commits intomasterfrom
feature/sponsor-pages-tab-tables
Open

feat: add sponsor pages tab, add customized and managed tables#771
tomrndom wants to merge 4 commits intomasterfrom
feature/sponsor-pages-tab-tables

Conversation

@tomrndom
Copy link

@tomrndom tomrndom commented Feb 2, 2026

ref:
https://app.clickup.com/t/86b7991aw
https://app.clickup.com/t/86b7991bq

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

Summary by CodeRabbit

  • New Features

    • Added a Pages tab in sponsor management (Edit Sponsor) to view and manage both managed and sponsor‑customized pages.
    • Two side‑by‑side tables with search, hide‑archived toggle, independent managed/customized lists, pagination, sorting, per‑page controls, totals, and row actions (edit, delete, archive). Add buttons for creating pages and using templates.
  • Localization

    • Added English translations for the sponsor Pages tab UI.

@coderabbitai
Copy link

coderabbitai bot commented Feb 2, 2026

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

Adds sponsor pages management: new action types and thunks to fetch managed and customized sponsor pages, a reducer and store entry for pagination/filtering state, a new SponsorPagesTab UI integrated into EditSponsorPage, and i18n entries for sponsor pages labels.

Changes

Cohort / File(s) Summary
Actions
src/actions/sponsor-pages-actions.js
Added four action constants and two thunks (getSponsorManagedPages, getSponsorCustomizedPages) that build query params, attach auth/tz, and manage loading/error lifecycle while fetching managed and customized sponsor pages.
Reducer & Store
src/reducers/sponsors/sponsor-page-pages-list-reducer.js, src/store.js
New reducer managing managedPages and customizedPages (pagination, sorting, term, hideArchived, summitTZ); registered in root reducers as sponsorPagePagesListState.
UI / Pages
src/pages/sponsors/sponsor-pages-tab/index.js, src/pages/sponsors/edit-sponsor-page.js
New connected SponsorPagesTab component added and mounted as a new tab in EditSponsorPage; handles searching, sorting, paging, hide-archived toggle, and dispatches fetch thunks.
Localization
src/i18n/en.json
Added pages_tab translation block containing sponsor pages UI keys (duplicate blocks inserted in file).

Sequence Diagram(s)

sequenceDiagram
    participant UI as SponsorPagesTab
    participant Redux as Actions/Thunks
    participant API as Backend API
    participant Reducer as PagesReducer
    participant Store as ReduxStore

    UI->>Redux: dispatch getSponsorManagedPages(sponsorId, params)
    UI->>Redux: dispatch getSponsorCustomizedPages(sponsorId, params)
    Redux->>API: GET /sponsors/{id}/managed-pages (token, tz, filters)
    Redux->>API: GET /sponsors/{id}/sponsor-pages (token, tz, filters)
    API-->>Redux: 200 managed pages payload
    API-->>Redux: 200 customized pages payload
    Redux->>Reducer: dispatch RECEIVE_SPONSOR_MANAGED_PAGES(payload)
    Redux->>Reducer: dispatch RECEIVE_SPONSOR_CUSTOMIZED_PAGES(payload)
    Reducer->>Store: update managedPages and customizedPages state
    Store-->>UI: mapStateToProps returns updated lists
    UI->>UI: re-render tables with new data
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • romanetar
  • smarcet

Poem

🐇 I hopped through commits, whiskers all a-twitch,

Pages and tabs in a neat little stitch.
Actions dispatched, reducers keep score,
Tables appear, and I hop for more!
📄🌿

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main changes: adding a sponsor pages tab with customized and managed tables, which aligns with the core functionality added across multiple files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/sponsor-pages-tab-tables

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🤖 Fix all issues with AI agents
In `@src/actions/sponsor-pages-actions.js`:
- Around line 37-43: The exported action types (REQUEST_SPONSOR_MANAGED_PAGES,
RECEIVE_SPONSOR_MANAGED_PAGES, REQUEST_SPONSOR_CUSTOMIZED_PAGES,
RECEIVE_SPONSOR_CUSTOMIZED_PAGES) are missing the perPage/hideArchived values in
their dispatched payloads and API requests; update the action creators that use
these constants so the dispatched REQUEST_* and RECEIVE_* actions include
perPage and hideArchived in the action.payload, and change the API query/body
param for archived filtering from whatever is currently used to is_archived
(true/false) so the reducer and UI receive is_archived for archive labels and
row state; apply the same change to the other similar action creators referenced
in the comment (lines 149-203 and 209-263) so all sponsor-managed/customized
page flows carry perPage, hideArchived and send is_archived to the backend.

In `@src/i18n/en.json`:
- Around line 2463-2478: Add a new i18n key "managed_pages" under the existing
"pages_tab" object in src/i18n/en.json (e.g., "pages_tab.managed_pages":
"Managed Pages") and update the component that renders the managed pages header
to consume pages_tab.managed_pages instead of displaying the raw i18n key;
ensure the component uses the same i18n path ("pages_tab.managed_pages") so the
header no longer falls back to the key string.

In `@src/pages/sponsors/sponsor-pages-tab/index.js`:
- Around line 120-140: The action handlers (handleArchiveCustomizedPage,
handleArchiveManagedPage, handleManagedEdit, handleManagedDelete,
handleCustomizedEdit, handleCustomizedDelete) are currently no-ops that only
console.log; either implement them to perform the real actions (e.g., open edit
UI or navigate to edit route in handleManagedEdit/handleCustomizedEdit; show
confirm modal then call the archive/delete API and update local state/refresh
list in
handleArchiveManagedPage/handleArchiveCustomizedPage/handleManagedDelete/handleCustomizedDelete;
handle success/error and loading state) or remove the action props from the
components that render the buttons until you implement these behaviors so users
don’t get non-functional buttons. Use the existing API/dispatch/navigation
utilities in the file to perform the calls and update state accordingly.
- Around line 115-118: handleSearch currently calls
getSponsorManagedPages(searchTerm) and getSponsorCustomizedPages(searchTerm)
which causes filters/paging (hideArchived, current page, pageSize, sort) to
reset; update handleSearch to preserve and forward the current
filter/paging/sort state: read the existing hideArchived, pagination (page,
pageSize) and sort state variables and pass them as additional arguments or an
options object to getSponsorManagedPages and getSponsorCustomizedPages (or
update those functions to accept an options param) so the search only changes
the searchTerm and does not reset hideArchived/paging/sort.
- Around line 195-202: Replace the incorrect i18n key used for the managed pages
header: in the managedPagesColumns initialization (variable managedPagesColumns
calling baseColumns and T.translate) swap
T.translate("edit_sponsor.pages_tab.managed_forms") for a pages-specific key
(for example T.translate("edit_sponsor.pages_tab.managed_pages")) and ensure
that corresponding i18n entry is added to the locale files so the new key exists
and returns the intended label.
- Around line 14-70: The module is calling undefined setters setOpenPopup and
setCustomFormEdit from button handlers (e.g., the buttons that open the add/edit
popups), causing a ReferenceError; declare state hooks at the top of the
component (add useState to the React import) such as an openPopup state with
setter setOpenPopup (initial false) and a customFormEdit state with setter
setCustomFormEdit (initial null or {}), then update the existing button handlers
that reference setOpenPopup and setCustomFormEdit to use these newly declared
setters so the popup logic (open/close and edit payload) works correctly.

In `@src/reducers/sponsors/sponsor-page-pages-list-reducer.js`:
- Around line 55-87: The reducer handlers for REQUEST_SPONSOR_MANAGED_PAGES and
REQUEST_SPONSOR_CUSTOMIZED_PAGES are wrong: they set a non-existent forms field
so the list never clears and they do not persist per-page changes; update the
objects under state.managedPages and state.customizedPages to clear pages (set
pages: []) instead of forms and copy/persist perPage from payload (e.g.,
perPage: payload.perPage || existing perPage) while keeping order, orderDir and
currentPage updates (refer to REQUEST_SPONSOR_MANAGED_PAGES,
REQUEST_SPONSOR_CUSTOMIZED_PAGES, state.managedPages and state.customizedPages
to locate the code).
- Around line 89-142: In the RECEIVE_SPONSOR_MANAGED_PAGES and
RECEIVE_SPONSOR_CUSTOMIZED_PAGES handlers fix the swapped module counts and
include archive state: in the pages mapping for both cases assign upload_mod to
a.modules_count.media_request_modules_count and download_mod to
a.modules_count.document_download_modules_count (they are currently reversed),
and add is_archived: a.is_archived to each page object so row/archive labels
render correctly; also ensure the API request that populates payload.response
includes the is_archived field so payload.response.data items contain
a.is_archived.

Comment on lines 2463 to 2478
"pages_tab": {
"alert_info": "To add a Sponsor Specific Page for this show's sponsor, click Add Page button. Note: this Page will be visible only to this sponsor for this show. The General Pages can only be managed on the Show's Pages section.",
"hide_archived": "Hide archived Pages",
"using_template": "Using Template",
"new_page": "New Page",
"pages": "pages",
"sponsor_customized_pages": "Customized Sponsor Pages",
"code": "Code",
"name": "Name",
"add_ons": "Add-ons",
"info_mod": "Info Mod",
"upload_mod": "Upload Mod",
"download_mod": "Download Mod",
"archive": "Archive",
"unarchive": "Unarchive"
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add a managed-pages label to match the new table header.

The UI renders a managed pages header, but there’s no dedicated label here. Add a key (and update the component to use it) to avoid falling back to the raw i18n key.

📝 Suggested addition
     "pages_tab": {
       "alert_info": "To add a Sponsor Specific Page for this show's sponsor, click Add Page button. Note: this Page will be visible only to this sponsor for this show. The General Pages can only be managed on the Show's Pages section.",
       "hide_archived": "Hide archived Pages",
       "using_template": "Using Template",
       "new_page": "New Page",
       "pages": "pages",
+      "managed_pages": "Managed Pages",
       "sponsor_customized_pages": "Customized Sponsor Pages",
       "code": "Code",
       "name": "Name",
       "add_ons": "Add-ons",
       "info_mod": "Info Mod",
       "upload_mod": "Upload Mod",
       "download_mod": "Download Mod",
       "archive": "Archive",
       "unarchive": "Unarchive"
     },
📝 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
"pages_tab": {
"alert_info": "To add a Sponsor Specific Page for this show's sponsor, click Add Page button. Note: this Page will be visible only to this sponsor for this show. The General Pages can only be managed on the Show's Pages section.",
"hide_archived": "Hide archived Pages",
"using_template": "Using Template",
"new_page": "New Page",
"pages": "pages",
"sponsor_customized_pages": "Customized Sponsor Pages",
"code": "Code",
"name": "Name",
"add_ons": "Add-ons",
"info_mod": "Info Mod",
"upload_mod": "Upload Mod",
"download_mod": "Download Mod",
"archive": "Archive",
"unarchive": "Unarchive"
},
"pages_tab": {
"alert_info": "To add a Sponsor Specific Page for this show's sponsor, click Add Page button. Note: this Page will be visible only to this sponsor for this show. The General Pages can only be managed on the Show's Pages section.",
"hide_archived": "Hide archived Pages",
"using_template": "Using Template",
"new_page": "New Page",
"pages": "pages",
"managed_pages": "Managed Pages",
"sponsor_customized_pages": "Customized Sponsor Pages",
"code": "Code",
"name": "Name",
"add_ons": "Add-ons",
"info_mod": "Info Mod",
"upload_mod": "Upload Mod",
"download_mod": "Download Mod",
"archive": "Archive",
"unarchive": "Unarchive"
},
🤖 Prompt for AI Agents
In `@src/i18n/en.json` around lines 2463 - 2478, Add a new i18n key
"managed_pages" under the existing "pages_tab" object in src/i18n/en.json (e.g.,
"pages_tab.managed_pages": "Managed Pages") and update the component that
renders the managed pages header to consume pages_tab.managed_pages instead of
displaying the raw i18n key; ensure the component uses the same i18n path
("pages_tab.managed_pages") so the header no longer falls back to the key
string.

Comment on lines 14 to 70
import React, { useEffect } from "react";
import { connect } from "react-redux";
import T from "i18n-react/dist/i18n-react";
import {
Box,
Button,
Checkbox,
FormControlLabel,
FormGroup,
Grid2
} from "@mui/material";
import AddIcon from "@mui/icons-material/Add";
import {
archiveSponsorCustomizedForm,
deleteSponsorCustomizedForm,
saveSponsorManagedForm,
unarchiveSponsorCustomizedForm
} from "../../../actions/sponsor-forms-actions";
import {
getSponsorManagedPages,
getSponsorCustomizedPages
} from "../../../actions/sponsor-pages-actions";
import CustomAlert from "../../../components/mui/custom-alert";
import SearchInput from "../../../components/mui/search-input";
import MuiTable from "../../../components/mui/table/mui-table";
// import AddSponsorFormTemplatePopup from "./components/add-sponsor-form-template-popup";
// import CustomizedFormPopup from "./components/customized-form/customized-form-popup";
import { DEFAULT_CURRENT_PAGE } from "../../../utils/constants";

const SponsorPagesTab = ({
term,
hideArchived,
managedPages,
customizedPages,
getSponsorManagedPages,
getSponsorCustomizedPages
}) => {
useEffect(() => {
getSponsorManagedPages();
getSponsorCustomizedPages();
}, []);

const handleManagedPageChange = (page) => {
const { perPage, order, orderDir } = managedPages;
getSponsorManagedPages(term, page, perPage, order, orderDir, hideArchived);
};

const handleManagedPerPageChange = (newPerPage) => {
const { currentPage, order, orderDir } = managedPages;
getSponsorManagedPages(
term,
currentPage,
newPerPage,
order,
orderDir,
hideArchived
);
Copy link

@coderabbitai coderabbitai bot Feb 2, 2026

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
# Check for references to the popup setters
rg -n "setOpenPopup|setCustomFormEdit" src/pages/sponsors/sponsor-pages-tab/index.js

Repository: fntechgit/summit-admin

Length of output: 278


🏁 Script executed:

wc -l src/pages/sponsors/sponsor-pages-tab/index.js

Repository: fntechgit/summit-admin

Length of output: 115


🏁 Script executed:

cat -n src/pages/sponsors/sponsor-pages-tab/index.js | head -100

Repository: fntechgit/summit-admin

Length of output: 3725


🏁 Script executed:

cat -n src/pages/sponsors/sponsor-pages-tab/index.js | sed -n '240,280p'

Repository: fntechgit/summit-admin

Length of output: 1563


🏁 Script executed:

# Check if useState is imported
rg -n "useState" src/pages/sponsors/sponsor-pages-tab/index.js

Repository: fntechgit/summit-admin

Length of output: 48


🏁 Script executed:

# Check lines around where state might be declared (after line 50)
cat -n src/pages/sponsors/sponsor-pages-tab/index.js | sed -n '50,120p'

Repository: fntechgit/summit-admin

Length of output: 2194


🏁 Script executed:

# Check the remaining section to see all state declarations and usage
cat -n src/pages/sponsors/sponsor-pages-tab/index.js | sed -n '310,347p'

Repository: fntechgit/summit-admin

Length of output: 1322


Define popup setters before using them.

setOpenPopup and setCustomFormEdit aren't declared in this module. Clicking either button at lines 256 or 268 will throw a ReferenceError at runtime.

🛠️ Suggested fix
-import React, { useEffect } from "react";
+import React, { useEffect, useState } from "react";
...
 const SponsorPagesTab = ({
   term,
   hideArchived,
   managedPages,
   customizedPages,
   getSponsorManagedPages,
   getSponsorCustomizedPages
 }) => {
+  const [openPopup, setOpenPopup] = useState(null);
+  const [customFormEdit, setCustomFormEdit] = useState(null);
📝 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
import React, { useEffect } from "react";
import { connect } from "react-redux";
import T from "i18n-react/dist/i18n-react";
import {
Box,
Button,
Checkbox,
FormControlLabel,
FormGroup,
Grid2
} from "@mui/material";
import AddIcon from "@mui/icons-material/Add";
import {
archiveSponsorCustomizedForm,
deleteSponsorCustomizedForm,
saveSponsorManagedForm,
unarchiveSponsorCustomizedForm
} from "../../../actions/sponsor-forms-actions";
import {
getSponsorManagedPages,
getSponsorCustomizedPages
} from "../../../actions/sponsor-pages-actions";
import CustomAlert from "../../../components/mui/custom-alert";
import SearchInput from "../../../components/mui/search-input";
import MuiTable from "../../../components/mui/table/mui-table";
// import AddSponsorFormTemplatePopup from "./components/add-sponsor-form-template-popup";
// import CustomizedFormPopup from "./components/customized-form/customized-form-popup";
import { DEFAULT_CURRENT_PAGE } from "../../../utils/constants";
const SponsorPagesTab = ({
term,
hideArchived,
managedPages,
customizedPages,
getSponsorManagedPages,
getSponsorCustomizedPages
}) => {
useEffect(() => {
getSponsorManagedPages();
getSponsorCustomizedPages();
}, []);
const handleManagedPageChange = (page) => {
const { perPage, order, orderDir } = managedPages;
getSponsorManagedPages(term, page, perPage, order, orderDir, hideArchived);
};
const handleManagedPerPageChange = (newPerPage) => {
const { currentPage, order, orderDir } = managedPages;
getSponsorManagedPages(
term,
currentPage,
newPerPage,
order,
orderDir,
hideArchived
);
import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import T from "i18n-react/dist/i18n-react";
import {
Box,
Button,
Checkbox,
FormControlLabel,
FormGroup,
Grid2
} from "@mui/material";
import AddIcon from "@mui/icons-material/Add";
import {
archiveSponsorCustomizedForm,
deleteSponsorCustomizedForm,
saveSponsorManagedForm,
unarchiveSponsorCustomizedForm
} from "../../../actions/sponsor-forms-actions";
import {
getSponsorManagedPages,
getSponsorCustomizedPages
} from "../../../actions/sponsor-pages-actions";
import CustomAlert from "../../../components/mui/custom-alert";
import SearchInput from "../../../components/mui/search-input";
import MuiTable from "../../../components/mui/table/mui-table";
// import AddSponsorFormTemplatePopup from "./components/add-sponsor-form-template-popup";
// import CustomizedFormPopup from "./components/customized-form/customized-form-popup";
import { DEFAULT_CURRENT_PAGE } from "../../../utils/constants";
const SponsorPagesTab = ({
term,
hideArchived,
managedPages,
customizedPages,
getSponsorManagedPages,
getSponsorCustomizedPages
}) => {
const [openPopup, setOpenPopup] = useState(null);
const [customFormEdit, setCustomFormEdit] = useState(null);
useEffect(() => {
getSponsorManagedPages();
getSponsorCustomizedPages();
}, []);
const handleManagedPageChange = (page) => {
const { perPage, order, orderDir } = managedPages;
getSponsorManagedPages(term, page, perPage, order, orderDir, hideArchived);
};
const handleManagedPerPageChange = (newPerPage) => {
const { currentPage, order, orderDir } = managedPages;
getSponsorManagedPages(
term,
currentPage,
newPerPage,
order,
orderDir,
hideArchived
);
🤖 Prompt for AI Agents
In `@src/pages/sponsors/sponsor-pages-tab/index.js` around lines 14 - 70, The
module is calling undefined setters setOpenPopup and setCustomFormEdit from
button handlers (e.g., the buttons that open the add/edit popups), causing a
ReferenceError; declare state hooks at the top of the component (add useState to
the React import) such as an openPopup state with setter setOpenPopup (initial
false) and a customFormEdit state with setter setCustomFormEdit (initial null or
{}), then update the existing button handlers that reference setOpenPopup and
setCustomFormEdit to use these newly declared setters so the popup logic
(open/close and edit payload) works correctly.

Copy link

Choose a reason for hiding this comment

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

@tomrndom please review

Copy link

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment on lines 89 to 142
case RECEIVE_SPONSOR_MANAGED_PAGES: {
const {
current_page: currentPage,
total,
last_page: lastPage
} = payload.response;

const pages = payload.response.data.map((a) => ({
id: a.id,
code: a.code,
name: a.name,
info_mod: a.modules_count.info_modules_count,
upload_mod: a.modules_count.document_download_modules_count,
download_mod: a.modules_count.media_request_modules_count
}));

return {
...state,
managedPages: {
...state.managedPages,
pages,
currentPage,
totalCount: total,
lastPage
}
};
}
case RECEIVE_SPONSOR_CUSTOMIZED_PAGES: {
const {
current_page: currentPage,
total,
last_page: lastPage
} = payload.response;

const pages = payload.response.data.map((a) => ({
id: a.id,
code: a.code,
name: a.name,
allowed_add_ons: a.allowed_add_ons,
info_mod: a.modules_count.info_modules_count,
upload_mod: a.modules_count.document_download_modules_count,
download_mod: a.modules_count.media_request_modules_count
}));

return {
...state,
customizedPages: {
...state.customizedPages,
pages,
currentPage,
totalCount: total,
lastPage
}
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Correct module counts and include archive state.

upload_mod/download_mod are swapped, and is_archived is missing, so archive labels/row state can’t be accurate. (Make sure the API request includes is_archived.)

🛠️ Suggested fix
       const pages = payload.response.data.map((a) => ({
         id: a.id,
         code: a.code,
         name: a.name,
         info_mod: a.modules_count.info_modules_count,
-        upload_mod: a.modules_count.document_download_modules_count,
-        download_mod: a.modules_count.media_request_modules_count
+        upload_mod: a.modules_count.media_request_modules_count,
+        download_mod: a.modules_count.document_download_modules_count,
+        is_archived: a.is_archived
       }));
       const pages = payload.response.data.map((a) => ({
         id: a.id,
         code: a.code,
         name: a.name,
         allowed_add_ons: a.allowed_add_ons,
         info_mod: a.modules_count.info_modules_count,
-        upload_mod: a.modules_count.document_download_modules_count,
-        download_mod: a.modules_count.media_request_modules_count
+        upload_mod: a.modules_count.media_request_modules_count,
+        download_mod: a.modules_count.document_download_modules_count,
+        is_archived: a.is_archived
       }));
🤖 Prompt for AI Agents
In `@src/reducers/sponsors/sponsor-page-pages-list-reducer.js` around lines 89 -
142, In the RECEIVE_SPONSOR_MANAGED_PAGES and RECEIVE_SPONSOR_CUSTOMIZED_PAGES
handlers fix the swapped module counts and include archive state: in the pages
mapping for both cases assign upload_mod to
a.modules_count.media_request_modules_count and download_mod to
a.modules_count.document_download_modules_count (they are currently reversed),
and add is_archived: a.is_archived to each page object so row/archive labels
render correctly; also ensure the API request that populates payload.response
includes the is_archived field so payload.response.data items contain
a.is_archived.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/pages/sponsors/sponsor-pages-tab/index.js`:
- Around line 253-256: Replace the Checkbox's uncontrolled "value" prop with the
controlled "checked" prop so the checkbox reflects the hideArchived state;
locate the Checkbox rendered in the sponsors tab (the one using
value={hideArchived} and onChange={handleHideArchived}) and change it to use
checked={hideArchived} while keeping onChange={handleHideArchived} so the UI
stays in sync with the hideArchived state.

@tomrndom tomrndom requested review from romanetar and smarcet February 3, 2026 00:31
name: a.name,
allowed_add_ons: a.allowed_add_ons,
info_mod: a.modules_count.info_modules_count,
upload_mod: a.modules_count.document_download_modules_count,
Copy link

Choose a reason for hiding this comment

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

@tomrndom this mapping is wrong

allowed_add_ons: a.allowed_add_ons,
info_mod: a.modules_count.info_modules_count,
upload_mod: a.modules_count.document_download_modules_count,
download_mod: a.modules_count.media_request_modules_count
Copy link

Choose a reason for hiding this comment

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

@tomrndom same here

code: a.code,
name: a.name,
allowed_add_ons: a.allowed_add_ons,
info_mod: a.modules_count.info_modules_count,
Copy link

Choose a reason for hiding this comment

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

@tomrndom wrong mapping

name: a.name,
allowed_add_ons: a.allowed_add_ons,
info_mod: a.modules_count.info_modules_count,
upload_mod: a.modules_count.media_request_modules_count,
Copy link

Choose a reason for hiding this comment

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

@tomrndom wrong mapping

const { currentPage, order, orderDir } = managedPages;
getSponsorManagedPages(
term,
currentPage,
Copy link

Choose a reason for hiding this comment

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

@tomrndom this is wrong should default to DEFAULT_CURRENT_PAGE

const { currentPage, order, orderDir } = customizedPages;
getSponsorCustomizedPages(
term,
currentPage,
Copy link

Choose a reason for hiding this comment

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

should be DEFAULT_CURRENT_PAGE


getSponsorCustomizedPages(
term,
currentPage,
Copy link

Choose a reason for hiding this comment

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

should be DEFAULT_CURRENT_PAGE

Copy link

@smarcet smarcet left a comment

Choose a reason for hiding this comment

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

@tomrndom please review

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 feature/sponsor-pages-tab-tables branch from 45f01d3 to 83cc52e Compare February 20, 2026 22:00
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/actions/sponsor-pages-actions.js`:
- Around line 127-135: The current getRequest call that dispatches
REQUEST_SPONSOR_MANAGED_PAGES and RECEIVE_SPONSOR_MANAGED_PAGES only calls
dispatch(stopLoading()) inside then(), so stopLoading() is never dispatched on
failures and the loading state can get stuck; update the promise chain for the
managed-pages request (the getRequest(...) invocation that uses
REQUEST_SPONSOR_MANAGED_PAGES / RECEIVE_SPONSOR_MANAGED_PAGES) to call
dispatch(stopLoading()) in a finally() block (mirror the cloneGlobalPage
pattern) so stopLoading() runs regardless of success or error, and apply the
same change to the analogous customized-pages request (the getRequest using the
customized action constants around the 187-195 area).

---

Duplicate comments:
In `@src/actions/sponsor-pages-actions.js`:
- Around line 108-113: The request params for fetching sponsor pages (the const
params with fields: "id,code,name,kind,modules_count,allowed_add_ons") are
missing the is_archived field; update that fields string to include is_archived
so the archive state is returned. Make the same change in the other request
block noted (the second params block around the customized/managed requests) so
both managed and customized fetches include is_archived.

In `@src/pages/sponsors/sponsor-pages-tab/index.js`:
- Around line 144-164: Handlers currently only log to console
(handleArchiveCustomizedPage, handleArchiveManagedPage, handleManagedEdit,
handleManagedDelete, handleCustomizedEdit, handleCustomizedDelete) leaving UI
clickable but non-functional; replace the console.log calls with calls to the
real implementations (e.g., call archivePage(item.id) /
archivePageManaged(item.id), editPage(item) / openEditModal(item),
deletePage(itemId) / showConfirmDelete(itemId), and the add button handlers with
openAddManagedPage() and openAddCustomizedPage()), or if those implementations
do not yet exist, disable or hide the corresponding buttons until you implement
functions like archivePage, editPage, deletePage, openAddManagedPage and
openAddCustomizedPage or wire them to existing action creators/modals so the UI
performs the expected actions rather than just logging.

Comment on lines +127 to +135
return getRequest(
createAction(REQUEST_SPONSOR_MANAGED_PAGES),
createAction(RECEIVE_SPONSOR_MANAGED_PAGES),
`${window.SPONSOR_PAGES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/managed-pages`,
authErrorHandler,
{ order, orderDir, page, perPage, term, hideArchived, summitTZ }
)(params)(dispatch).then(() => {
dispatch(stopLoading());
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Ensure loading state clears on failures.

stopLoading() only runs on success. If the request fails, loading can remain stuck. Mirror the cloneGlobalPage pattern and use finally.

🛠️ Suggested fix
-    return getRequest(
+    return getRequest(
       createAction(REQUEST_SPONSOR_MANAGED_PAGES),
       createAction(RECEIVE_SPONSOR_MANAGED_PAGES),
       `${window.SPONSOR_PAGES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/managed-pages`,
       authErrorHandler,
       { order, orderDir, page, perPage, term, hideArchived, summitTZ }
-    )(params)(dispatch).then(() => {
-      dispatch(stopLoading());
-    });
+    )(params)(dispatch)
+      .finally(() => dispatch(stopLoading()));

Apply to both managed and customized requests.

Also applies to: 187-195

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

In `@src/actions/sponsor-pages-actions.js` around lines 127 - 135, The current
getRequest call that dispatches REQUEST_SPONSOR_MANAGED_PAGES and
RECEIVE_SPONSOR_MANAGED_PAGES only calls dispatch(stopLoading()) inside then(),
so stopLoading() is never dispatched on failures and the loading state can get
stuck; update the promise chain for the managed-pages request (the
getRequest(...) invocation that uses REQUEST_SPONSOR_MANAGED_PAGES /
RECEIVE_SPONSOR_MANAGED_PAGES) to call dispatch(stopLoading()) in a finally()
block (mirror the cloneGlobalPage pattern) so stopLoading() runs regardless of
success or error, and apply the same change to the analogous customized-pages
request (the getRequest using the customized action constants around the 187-195
area).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/pages/sponsors/sponsor-pages-tab/index.js`:
- Around line 51-54: The customized pages fetch is commented out inside the
mount effect so the customized list remains empty until user action; update the
useEffect in sponsor-pages-tab to call getSponsorCustomizedPages() on mount
(i.e., uncomment or add the call alongside getSponsorManagedPages()) so the
component fetches both managed and customized pages when it mounts; ensure you
invoke the existing getSponsorCustomizedPages() function within the same
useEffect (and preserve any existing dependency array).

---

Duplicate comments:
In `@src/pages/sponsors/sponsor-pages-tab/index.js`:
- Around line 151-171: The action handlers (handleArchiveCustomizedPage,
handleArchiveManagedPage, handleManagedEdit, handleManagedDelete,
handleCustomizedEdit, handleCustomizedDelete) are currently no-ops that only
console.log; either implement the real flows or remove/disable the action props
so the UI doesn't present non-functional buttons. Fix by wiring each handler to
the appropriate business logic or parent callbacks (e.g., call the existing
archive/edit/delete API functions or dispatch actions such as
archiveManagedPage(item.id), editManagedPage(item), deleteManagedPage(itemId),
archiveCustomizedPage(...), editCustomizedPage(...), deleteCustomizedPage(...)),
or if those flows are not ready, return null/omit the action prop or render the
button disabled with a tooltip. Ensure the handlers call the real service or
prop callback and handle success/error states instead of logging.

Comment on lines 51 to 54
useEffect(() => {
getSponsorManagedPages();
// getSponsorCustomizedPages();
}, []);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fetch customized pages on mount (currently commented out).

Line 53 leaves the customized list empty until a user action triggers a fetch. If the table is meant to load on entry, this should be enabled.

🛠️ Suggested fix
 useEffect(() => {
   getSponsorManagedPages();
-  // getSponsorCustomizedPages();
+  getSponsorCustomizedPages();
 }, []);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/sponsors/sponsor-pages-tab/index.js` around lines 51 - 54, The
customized pages fetch is commented out inside the mount effect so the
customized list remains empty until user action; update the useEffect in
sponsor-pages-tab to call getSponsorCustomizedPages() on mount (i.e., uncomment
or add the call alongside getSponsorManagedPages()) so the component fetches
both managed and customized pages when it mounts; ensure you invoke the existing
getSponsorCustomizedPages() function within the same useEffect (and preserve any
existing dependency array).

Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
@tomrndom tomrndom force-pushed the feature/sponsor-pages-tab-tables branch from e98aa2a to b1ef29b Compare February 21, 2026 00:42
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.

2 participants