Improve Watchlist UX with Richer Metadata, Progress Tracking & Personalized Insights (#239)#439
Improve Watchlist UX with Richer Metadata, Progress Tracking & Personalized Insights (#239)#439diksha78dev wants to merge 8 commits into
Conversation
…nd personalized insights - Add watchlist metadata persistence (checklist, notes, progress) via localStorage - Display richer org cards with: category, competition level, codebase difficulty, tech stack - Add progress bar and interactive checklist for proposal preparation - Add personal notes textarea per organization - Generate personalized AI insights based on watchlist progress and top technologies - Responsive grid layout adapts to mobile/tablet/desktop - Maintains minimal code philosophy with no external dependencies
|
@diksha78dev is attempting to deploy a commit to the s3dfx-cyber's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds per-organization watchlist persistence in localStorage (checklist booleans, notes, progress, updatedAt), wires checklist and notes inputs to update/save helpers, preserves grid pagination on bookmark toggle, and enriches renderWatchlist to show progress bars, persisted checklists, and notes. ChangesWatchlist Metadata and Enhancement
Sequence Diagram(s)sequenceDiagram
participant User
participant WatchlistUI
participant MetaStore as localStorage:watchlist_meta
participant Renderer as renderWatchlist
User->>WatchlistUI: toggle checklist / edit notes
WatchlistUI->>MetaStore: updateChecklistItem / updateOrgNotes
MetaStore-->>Renderer: stored meta updated
Renderer->>WatchlistUI: re-render cards & progress
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🚀 Pull Request OpenedHi @diksha78dev! Here's your current ranking:
Current Rank: #9 Current Score: 12 Keep contributing to climb the leaderboard 📈 |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
index.html (1)
2090-2100: 💤 Low value
getOrgMetamutatesupdatedAton every read.Treating a getter as a writer makes it hard to reason about who last touched a record and causes
updatedAtto drift purely from rendering. Consider only settingupdatedAtfrom the explicit mutators (updateChecklistItem,updateOrgNotes) and leavinggetOrgMetaside-effect-free for "first-create" cases.♻️ Suggested change
function getOrgMeta(meta, orgName) { if (!meta[orgName]) { meta[orgName] = { checklist: { read_ideas: false, intro_contact: false, first_pr: false, proposal: false }, notes: '', progress: 0, - updatedAt: new Date().toISOString() + updatedAt: null }; } return meta[orgName]; }🤖 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 `@index.html` around lines 2090 - 2100, getOrgMeta currently mutates the org entry by setting updatedAt every time it is called, which causes reads to look like writes; change getOrgMeta to be side-effect-free by only creating and returning a default meta object when meta[orgName] is missing without setting updatedAt there, and instead update updatedAt only inside the explicit mutators (updateChecklistItem and updateOrgNotes) when they actually change data; locate getOrgMeta, updateChecklistItem, and updateOrgNotes in the diff and move or add updatedAt assignments into those mutator functions so creation uses a static default (no timestamp) and all real timestamp updates occur in the mutators.
🤖 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 `@index.html`:
- Line 2149: Inline JS handlers that interpolate org.name break on quotes;
replace the inline onchange and oninput usage with data attributes and delegated
listeners: render the checkbox list items and notes textarea/input with data
attributes (e.g., data-checklist-org, data-checklist-key on each checkbox and
data-notes-org on the notes control) instead of calling updateChecklistItem(...)
or updateOrgNotes(...) inline, then extend attachOrgCardListeners to add
delegated event handlers (change for checkboxes, input/change for notes) that
read org and key from event.target.dataset and call the existing
updateChecklistItem and updateOrgNotes functions; this keeps behavior identical
but avoids JS-string injection and matches the existing data-* +
attachOrgCardListeners pattern.
- Line 2186: The textarea uses an inline onchange handler which only fires on
blur, causing typed notes to be lost if the user navigates away; update the
textarea element that currently calls updateOrgNotes('${org.name}', this.value)
(and references meta.notes/escapeHtml) to use oninput instead of onchange so
updates happen as the user types, or alternatively keep oninput and also call
updateOrgNotes on blur to guarantee persistence; ensure the same updateOrgNotes
function continues to accept (orgName, value) and works with the data reflected
by escapeHtml/meta.notes.
- Line 2187: The Remove button in the org card is missing the required CSS class
so attachOrgCardListeners (which binds to elements matching
.bookmark-btn[data-bookmark-org]) never attaches its click handler; fix by
adding the bookmark-btn class to the Remove button element (the button with
data-bookmark-org="${escapeHtml(org.name)}") so it matches
.bookmark-btn[data-bookmark-org] and the existing attachOrgCardListeners logic
will bind the un-bookmark click behavior.
- Around line 2197-2200: avgProgress is computed by summing
Object.values(watchlistMeta) but dividing by bookmarks.length, causing inflated
averages because watchlistMeta contains stale entries; change the calculation to
iterate only over current bookmarks (e.g., map bookmarks to their corresponding
watchlistMeta entries, sum each entry's progress || 0 and divide by
bookmarks.length, guarding against zero-length bookmarks) and optionally remove
stale keys from watchlistMeta inside toggleBookmark when an org is unbookmarked
to keep storage in sync.
---
Nitpick comments:
In `@index.html`:
- Around line 2090-2100: getOrgMeta currently mutates the org entry by setting
updatedAt every time it is called, which causes reads to look like writes;
change getOrgMeta to be side-effect-free by only creating and returning a
default meta object when meta[orgName] is missing without setting updatedAt
there, and instead update updatedAt only inside the explicit mutators
(updateChecklistItem and updateOrgNotes) when they actually change data; locate
getOrgMeta, updateChecklistItem, and updateOrgNotes in the diff and move or add
updatedAt assignments into those mutator functions so creation uses a static
default (no timestamp) and all real timestamp updates occur in the mutators.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: fe5f8ba4-ed43-408f-b273-b74a14ac9968
📒 Files selected for processing (1)
index.html
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: cubic · AI code reviewer
🧰 Additional context used
🪛 GitHub Check: SonarCloud Code Analysis
index.html
[warning] 2205-2205: Unexpected negated condition.
[warning] 2149-2149: Prefer String#replaceAll() over String#replace().
There was a problem hiding this comment.
1 issue found across 1 file
Confidence score: 3/5
- There is a concrete user-facing accuracy risk in
index.html:avgProgressis being computed with stalewatchlistMetaentries, which can inflate the displayed insight percentage after orgs are removed. - Given the issue is medium severity (6/10) with high confidence (9/10), this introduces some regression risk in metrics correctness rather than a broad functional break.
- This looks localized to aggregation logic, so the PR may still be mergeable, but the calculation should be corrected to use only current
bookmarks. - Pay close attention to
index.html- ensureavgProgressexcludes removed-org metadata and reflects only active bookmark data.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="index.html">
<violation number="1" location="index.html:2197">
P2: Compute `avgProgress` from the current `bookmarks` only. Including stale `watchlistMeta` entries from removed orgs inflates the insight percentage.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="index.html">
<violation number="1" location="index.html:2205">
P2: Reusing the `bookmark-btn` class on the watchlist “Remove” action applies icon-specific styles (1.25rem font + scale hover) to a full-width text button, causing unintended UI behavior.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
|
efb21b2 to
8808e3b
Compare
There was a problem hiding this comment.
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 `@index.html`:
- Around line 2125-2188: The file contains unresolved git conflict markers;
remove the conflict lines and merge both changes so the watchlist meta functions
(loadWatchlistMeta, saveWatchlistMeta, getOrgMeta, updateChecklistItem,
updateOrgNotes) are preserved and the new pagination helper
refreshOrgGridPreservingVisibleCount() is present; then update toggleBookmark to
call refreshOrgGridPreservingVisibleCount() after updating localStorage
(replacing the renderOrgs(false) call) so bookmarking preserves visibleCount and
pagination state. Ensure no leftover <<<<<<<, =======, or >>>>>>> markers
remain.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c9fcfc72-8692-4024-8d03-ef5123b395eb
📒 Files selected for processing (1)
index.html
📜 Review details
🔇 Additional comments (4)
index.html (4)
724-725: LGTM!
1974-1991: LGTM!
2210-2255: LGTM!
2257-2272: LGTM!
cd249dc to
15e7b6a
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@index.html`:
- Around line 2139-2149: getOrgMeta currently returns stored objects as-is which
can have malformed checklist/progress/notes; update getOrgMeta to defensively
normalize and return a well-shaped org object: ensure checklist exists and
contains the boolean keys read_ideas, intro_contact, first_pr, proposal (default
false), ensure notes is a string (default ''), ensure progress is a number
(compute from checklist if missing), and ensure updatedAt is an ISO string
(default new Date().toISOString()); apply this normalization before returning
meta[orgName] so callers like whoever reads meta.checklist or computes progress
(lines referenced around getOrgMeta and the progress calculation) cannot crash
on stale shapes.
- Around line 2135-2137: The saveWatchlistMeta function writes directly to
localStorage and can throw in restricted/storage-quota environments; wrap the
localStorage write in a guard that first checks for the existence of
window/localStorage (or typeof localStorage !== 'undefined') and then perform
the setItem inside a try/catch, swallowing or logging the error and falling back
to a safe no-op or in-memory cache so note input events (caller around the notes
input) cannot break watchlist interactions; update saveWatchlistMeta to
implement this guarded write and ensure any callers still work if the write
fails.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 49c9116a-9e7c-4d0b-bfb5-deb3a7a96301
📒 Files selected for processing (1)
index.html
📜 Review details
🧰 Additional context used
🪛 GitHub Check: SonarCloud Code Analysis
index.html
[warning] 2265-2265: Unexpected negated condition.
[warning] 2207-2207: Prefer String#replaceAll() over String#replace().
🔇 Additional comments (1)
index.html (1)
724-725: LGTM!Also applies to: 1975-1991, 2193-2193, 2208-2246, 2252-2266
- Enforce 200-char limit in updateOrgNotes() (browser+code validation) - Prevents storage issues from bypassed maxlength attribute Signed-off-by: diksha78dev <diksha78dev@gmail.com>
b1c842b to
26743ba
Compare
🚦 PR Review Pipeline
ℹ️ Stage 1 checks
ℹ️ Pipeline legend✅ Passed · ❌ Failed · ⏳ Pending · 🔒 Blocked · 👀 Under review Bots never auto-approve or auto-merge. Humans make every final decision. Last updated: Wed, 13 May 2026 11:35:38 GMT |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
index.html (1)
2167-2174: ⚡ Quick winPrune
watchlist_metawhen an org is unbookmarked.
toggleBookmarkonly mutatesbookmarkedSet/bookmarks, so removing an org leaves its checklist + notes inlocalStorageindefinitely. Not user-visible today (avgProgress now correctly iteratesbookmarks), but the keyspace grows unbounded and re-bookmarking surprises the user with old progress/notes from a previous session. Cheap to clean up here.♻️ Suggested cleanup
function toggleBookmark(e, name) { if (e) e.stopPropagation(); - if (bookmarkedSet.has(name)) bookmarkedSet.delete(name); - else bookmarkedSet.add(name); + if (bookmarkedSet.has(name)) { + bookmarkedSet.delete(name); + const meta = loadWatchlistMeta(); + if (meta[name]) { + delete meta[name]; + saveWatchlistMeta(meta); + } + } else { + bookmarkedSet.add(name); + } localStorage.setItem('bookmarks', JSON.stringify([...bookmarkedSet])); refreshOrgGridPreservingVisibleCount(); renderWatchlist(); }🤖 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 `@index.html` around lines 2167 - 2174, When an org is removed in toggleBookmark, also remove its metadata from the watchlist_meta stored in localStorage: inside toggleBookmark (the function that updates bookmarkedSet and writes 'bookmarks'), detect the branch where bookmarkedSet.delete(name) runs and then load localStorage.getItem('watchlist_meta'), JSON.parse it (safely defaulting to {}), delete the property for the same name, and write the updated object back with localStorage.setItem('watchlist_meta', JSON.stringify(updatedMeta)); keep the rest of the function (refreshOrgGridPreservingVisibleCount and renderWatchlist) unchanged.
🤖 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 `@index.html`:
- Around line 2139-2147: updateChecklistItem currently calls renderWatchlist()
which rebuilds the DOM and loses each <details> open state; modify
updateChecklistItem to preserve the checklist drawer state by either updating
the checkbox and progress DOM in place (find the org card element for orgName
and update its checkbox input.checked, progress text/value and updatedAt without
calling renderWatchlist) or persist the <details> open state in the meta object
(use loadWatchlistMeta/getOrgMeta to add an org.open boolean, set it before
saveWatchlistMeta, and update renderWatchlist to render <details open> when
org.open is true) and ensure getOrgMeta/saveWatchlistMeta and renderWatchlist
respect that flag so toggling a checkbox does not collapse the drawer.
---
Nitpick comments:
In `@index.html`:
- Around line 2167-2174: When an org is removed in toggleBookmark, also remove
its metadata from the watchlist_meta stored in localStorage: inside
toggleBookmark (the function that updates bookmarkedSet and writes 'bookmarks'),
detect the branch where bookmarkedSet.delete(name) runs and then load
localStorage.getItem('watchlist_meta'), JSON.parse it (safely defaulting to {}),
delete the property for the same name, and write the updated object back with
localStorage.setItem('watchlist_meta', JSON.stringify(updatedMeta)); keep the
rest of the function (refreshOrgGridPreservingVisibleCount and renderWatchlist)
unchanged.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 480d6e69-0d4a-490a-a706-d33dec63df34
📒 Files selected for processing (1)
index.html
📜 Review details
🧰 Additional context used
🪛 GitHub Check: SonarCloud Code Analysis
index.html
[warning] 2114-2114: Unexpected negated condition.
[warning] 2134-2134: Prefer Number.isNaN over isNaN.
[warning] 2196-2196: Prefer String#replaceAll() over String#replace().
[warning] 2254-2254: Unexpected negated condition.
🔇 Additional comments (4)
index.html (4)
724-725: LGTM!
1943-1960: LGTM!
2094-2111: LGTM!
2176-2256: LGTM!
6e42611 to
ea5a978
Compare
|



NSOC26
Description
Enhances the watchlist section with richer organization metadata, interactive progress tracking, and personalized AI recommendations based on user activity.
Related Issue
Fixes #239
Type of Change
Changes Made
watchlist_metakey stores all user progress persistentlyTesting