Skip to content

feat: improve attendee notes access and display - #1031

Open
santipalenque wants to merge 1 commit into
masterfrom
feature/update-attendee-notes
Open

feat: improve attendee notes access and display#1031
santipalenque wants to merge 1 commit into
masterfrom
feature/update-attendee-notes

Conversation

@santipalenque

@santipalenque santipalenque commented Jul 31, 2026

Copy link
Copy Markdown

https://app.clickup.com/t/9014802374/86b72t1x0

Summary by CodeRabbit

  • Enhancements
    • Improved attendee form interactions, validation, submission, and section visibility.
    • Added a dedicated notes panel for clearer note management, including sorting, searching, exporting, and empty states.
    • Admin notes now open and display more consistently across attendee and ticket editing screens.
    • Updated translations for note-related labels and messages.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

AttendeeForm now uses hooks for state, validation, submission, and section visibility. NotesPanel provides controlled admin-notes rendering with updated translations. The attendee form and edit-ticket page now use the renamed panel component.

Changes

Attendee and notes panel refactor

Layer / File(s) Summary
Controlled NotesPanel and translations
src/components/notes/notes-panel.js, src/i18n/en.json
NotesPanel now renders inside a controlled Panel, fetches notes on mount, updates table labels, and uses the notes_panel translation namespace.
Hook-based attendee form
src/components/forms/attendee-form/attendee-form.js
AttendeeForm now uses hooks for entity and error state, validation, immutable submission updates, field handlers, tag creation, and independent section visibility.
Ticket-page notes integration
src/pages/orders/edit-ticket-page.js
The edit-ticket page now renders NotesPanel with attendee and ticket identifiers, controlled visibility, and toggle handling that accepts missing events.

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

Possibly related PRs

Suggested reviewers: caseylocker

🚥 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 clearly summarizes the main changes to attendee notes access and display.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/update-attendee-notes

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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/components/notes/notes-panel.js`:
- Around line 58-61: Update the confirmation message construction in the delete
flow around the msg object to remove the extra literal separator before noteId,
relying on the trailing space provided by
T.translate("notes_panel.remove_warning"). Preserve the existing translated
warning text and note ID in the rendered dialog.
- Around line 123-125: Update the showColumns calculation to call the standard
columns.includes method when filtering tableColumns, replacing the invalid
columns.include call while preserving the existing fallback to all tableColumns.
- Around line 41-51: Update the notes-loading useEffect to depend on attendeeId,
ticketId, open, and onToggle, while preventing completions from previous
requests from toggling current accordion state or updating stale data; retain
cleanup via clearNotesParams. Correct the columns method to includes and remove
the extra space in the delete warning text.
🪄 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: 473fef30-6a90-4c97-ad66-01cedbc8d9c0

📥 Commits

Reviewing files that changed from the base of the PR and between 54e0bd4 and 88bbf52.

📒 Files selected for processing (4)
  • src/components/forms/attendee-form/attendee-form.js
  • src/components/notes/notes-panel.js
  • src/i18n/en.json
  • src/pages/orders/edit-ticket-page.js

Comment on lines +41 to +51
useEffect(() => {
getNotes(attendeeId, ticketId, term, 1, perPage, order, orderDir).then(
() => {
if (!open) onToggle();
}
);

return () => {
clearNotesParams();
};
}, []);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check for key-based remounting of AttendeeForm/EditTicketPage on id changes.
rg -n '<AttendeeForm' -C5
rg -n '<EditTicketPage' -C5 --type=js
rg -n 'ticket_id' -C3 src/pages/orders/edit-ticket-page.js

Repository: fntechgit/summit-admin

Length of output: 160


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- NotesPanel implementation ---'
sed -n '1,220p' src/components/notes/notes-panel.js
printf '%s\n' '--- AttendeeForm call site ---'
sed -n '390,455p' src/components/forms/attendee-form/attendee-form.js
printf '%s\n' '--- EditTicketPage call site and effects ---'
sed -n '1,100p' src/pages/orders/edit-ticket-page.js
sed -n '425,475p' src/pages/orders/edit-ticket-page.js
printf '%s\n' '--- NotesPanel references and key props ---'
rg -n -C5 'NotesPanel|<AttendeeForm|<EditTicketPage|key=' src --glob '*.js'
printf '%s\n' '--- columns prop usage ---'
rg -n -C3 'columns|include\\(' src/components/notes src --glob '*.js'
printf '%s\n' '--- remove_warning translations ---'
rg -n -C2 'remove_warning' .

Repository: fntechgit/summit-admin

Length of output: 50379


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- AttendeeForm state and toggleSection ---'
rg -n -C8 'toggleSection|openSections|useState' src/components/forms/attendee-form/attendee-form.js | head -160
printf '%s\n' '--- AttendeeForm and EditTicketPage route declarations ---'
rg -n -C6 'attendee-form|AttendeeForm|edit-ticket-page|EditTicketPage|ticket/:|ticket_id|attendee_id' src --glob '*.js' --glob '*.jsx' | head -240
printf '%s\n' '--- All NotesPanel call sites only ---'
rg -n -C4 'NotesPanel' src --glob '*.js' --glob '*.jsx'
printf '%s\n' '--- Translation files containing remove_warning ---'
rg -l '"remove_warning"' . | while IFS= read -r file; do
  printf '%s\n' "--- $file"
  rg -n -C2 '"remove_warning"' "$file"
done
printf '%s\n' '--- Notes state shape and actions ---'
rg -n -C6 'notesState|columns:|getNotes|clearNotesParams' src/actions src/reducers src --glob '*.js' | head -260

Repository: fntechgit/summit-admin

Length of output: 50378


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- AttendeeForm consumers and route paths ---'
rg -n -C5 'AttendeeForm|EditTicketPage|edit-ticket|edit_attendee|attendees?/|tickets?/' src/pages src/routes src --glob '*.js' --glob '*.jsx' 2>/dev/null | head -260
printf '%s\n' '--- Notes reducer and action request completion ---'
sed -n '1,230p' src/reducers/notes-reducer.js 2>/dev/null || true
sed -n '1,195p' src/actions/notes-actions.js
printf '%s\n' '--- Targeted static verifier ---'
python3 - <<'PY'
import json
from pathlib import Path

notes = Path("src/components/notes/notes-panel.js").read_text()
translation = json.loads(Path("src/i18n/en.json").read_text())
warning = translation["notes_panel"]["remove_warning"]
print("effect_has_empty_deps:", "  }, []);" in notes)
print("uses_columns_include:", "columns.include(c.columnKey)" in notes)
print("remove_warning_repr:", repr(warning))
print("rendered_delete_text_repr:", repr(f"{warning} 123"))
print("double_space_in_rendered_delete_text:", "  " in f"{warning} 123")
PY

Repository: fntechgit/summit-admin

Length of output: 23264


Refetch notes when attendeeId or ticketId changes. The empty dependency array captures stale identifiers and accordion state. Use current open and onToggle, and ignore completions from previous requests. Also replace columns.include(...) with columns.includes(...) and remove the extra space in the delete warning.

🤖 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/components/notes/notes-panel.js` around lines 41 - 51, Update the
notes-loading useEffect to depend on attendeeId, ticketId, open, and onToggle,
while preventing completions from previous requests from toggling current
accordion state or updating stale data; retain cleanup via clearNotesParams.
Correct the columns method to includes and remove the extra space in the delete
warning text.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@santipalenque Confirmed this part applies. Verified that EditSummitAttendeePage.componentDidUpdate and EditTicketPage's useEffect(..., [match.params.ticket_id]) both re-fetch the entity without unmounting the tree when the route id changes — so NotesPanel can stay mounted while showing a different attendee's/ticket's notes.

That said, it's not a regression introduced by this PR: the previous Notes component had the exact same useEffect(() => { getNotes(...); ... }, []) with no attendeeId/ticketId in its deps, so this predates this change. Worth fixing while the file is already being touched, but flagging it as inherited rather than newly introduced.

Comment on lines 58 to 61
const msg = {
title: T.translate("general.are_you_sure"),
text: `${T.translate("notes.remove_warning")} ${noteId}`,
text: `${T.translate("notes_panel.remove_warning")} ${noteId}`,
type: "warning"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Delete-confirmation text will render a double space.

text: \${T.translate("notes_panel.remove_warning")} ${noteId}`adds a literal space before${noteId}. The translation "notes_panel.remove_warning"insrc/i18n/en.json` already ends with a trailing space, so the rendered dialog shows two spaces between "note" and the ID.

✏️ Proposed fix
-    "remove_warning": "Are you sure you want to delete note ",
+    "remove_warning": "Are you sure you want to delete note",
🤖 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/components/notes/notes-panel.js` around lines 58 - 61, Update the
confirmation message construction in the delete flow around the msg object to
remove the extra literal separator before noteId, relying on the trailing space
provided by T.translate("notes_panel.remove_warning"). Preserve the existing
translated warning text and note ID in the rendered dialog.

Comment on lines +123 to +125
const showColumns = columns
? tableColumns.filter((c) => columns.include(c.columnKey))
: tableColumns;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -e
file="$(fd -t f '^notes-panel\.js$' . | head -n 1)"
printf '%s\n' "FILE=$file"
ast-grep outline "$file" --match 'showColumns' --view expanded || true
sed -n '100,140p' "$file"
printf '%s\n' '--- columns references ---'
rg -n -C 3 '\bcolumns\b|notes-panel|NotesPanel' . -g '*.js' -g '*.jsx' -g '*.ts' -g '*.tsx'

Repository: fntechgit/summit-admin

Length of output: 50379


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- NotesPanel definition and prop types ---'
sed -n '1,55p' src/components/notes/notes-panel.js
sed -n '195,225p' src/components/notes/notes-panel.js
printf '%s\n' '--- NotesPanel call sites ---'
rg -n -B 8 -A 16 '<NotesPanel|<NotesPanel\b' src
printf '%s\n' '--- Runtime method check ---'
node - <<'JS'
const columns = ["id"];
console.log({
  includesType: typeof columns.includes,
  includeType: typeof columns.include
});
try {
  columns.include("id");
} catch (error) {
  console.log(`${error.name}: ${error.message}`);
}
JS

Repository: fntechgit/summit-admin

Length of output: 5951


Replace columns.include(...) with columns.includes(...). When columns is provided, the current call throws TypeError: columns.include is not a function.

🤖 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/components/notes/notes-panel.js` around lines 123 - 125, Update the
showColumns calculation to call the standard columns.includes method when
filtering tableColumns, replacing the invalid columns.include call while
preserving the existing fallback to all tableColumns.

Copilot AI 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.

Pull request overview

This PR improves how admin/attendee notes are accessed and displayed by introducing a dedicated NotesPanel component and wiring it into both ticket editing and attendee editing flows, alongside related i18n key updates.

Changes:

  • Replaced the previous notes section usage with a reusable NotesPanel in ticket and attendee editing screens.
  • Refactored AttendeeForm from a class component to a function component with hooks and independent section open/close state.
  • Updated English translations to support the new notes panel labels/messages and moved the “note created” success message key.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/pages/orders/edit-ticket-page.js Switches ticket admin notes UI to the new NotesPanel and makes section toggle event handling null-safe.
src/i18n/en.json Adjusts translation keys for notes vs. notes panel and removes unused admin notes labels.
src/components/notes/notes-panel.js Introduces/renames the notes UI into a dedicated panel component with table/search/export behaviors.
src/components/forms/attendee-form/attendee-form.js Converts attendee form to hooks, updates section toggling, and embeds NotesPanel for attendee notes.
Suppressed comments (2)

src/components/notes/notes-panel.js:46

  • The initial load effect toggles the panel after the getNotes promise resolves using the initial open value from the mount render. If the user opens/closes the panel while the request is in flight, this callback can flip the panel back to the opposite state unexpectedly.
    src/components/notes/notes-panel.js:125
  • columns.include(...) is not a standard Array API (the standard method is includes). If columns is ever provided as an array (the likely intent), this will throw at runtime.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +51 to +52
// field dint change , so remove it from submit
delete copyOfEntity[f];
}) => {
const [newNote, setNewNote] = useState("");

useEffect(() => {

@smarcet smarcet Aug 3, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@santipalenque This useEffect closes over open and onToggle at mount time (empty dep array), then calls onToggle() once getNotes resolves — and that stale call can silently undo a user's own action.

In edit-ticket-page.js, showSection is a single shared string across refund_requests/admin_notes/audit_log (mutually exclusive), initialized to "main". Since mount always happens with showSection === "main", the closure's toggleSection deterministically resolves to setShowSection("admin_notes") — a literal (non-functional) set. If an admin opens "Refund Requests" or "Audit Log" while the notes request is still in flight (any nonzero latency), that panel gets forcibly closed and replaced with "Admin Notes" the moment the fetch resolves, with no visual warning.

In attendee-form.js, toggleSection uses a functional update (setOpenSections(prev => ...)), so the flip itself is safe, but the gate if (!open) is still the stale mount-time false — meaning the deferred call always fires a toggle once. If the admin manually opens "Admin Notes" before the fetch resolves, this closes it right back.

Suggested fix: don't gate on the closed-over open/onToggle. Track "already auto-opened" and the current open state via a useRef synced every render, and expose a dedicated idempotent onOpen rather than reusing the generic toggle. Note: simply adding attendeeId, ticketId, open, onToggle to the effect's deps (as another bot comment on this PR suggests) would introduce a different bug — it would re-run getNotes/clearNotesParams on every panel toggle.

return copyOfEntity;
};

const AttendeeForm = ({

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@santipalenque This PR's commit message describes moving the notes panel and adding auto-open, but the diff also rewrites the entire AttendeeForm from a class component to hooks — validation (validate), submission (triggerFormSubmit, handleSubmit), tag creation (handleNewTag), and unchanged-field stripping (removeUnchangedFields) all moved to a new state/effect model. That's the attendee save/validate pipeline, not just the notes panel.

yarn jest src/components/forms/attendee-form src/components/notes src/pages/orders currently matches zero test files, and a repo-wide search finds no test anywhere referencing AttendeeForm, NotesPanel, or notes-panel — so this rewrite ships with no regression coverage at all.

Suggested fix: add a behavioral test class for AttendeeForm covering required-field validation, that onSubmit still receives a removeUnchangedFields-filtered payload after submit, and that the form resyncs when the entity prop changes — per summit-admin-testing-patterns.md's component/page test guidance.

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

@santipalenque please review

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