Skip to content

refactor: move mobile modules into domain directory#187

Closed
jtn0123 wants to merge 2 commits into
mainfrom
jtn-128-move-mobile-domain
Closed

refactor: move mobile modules into domain directory#187
jtn0123 wants to merge 2 commits into
mainfrom
jtn-128-move-mobile-domain

Conversation

@jtn0123
Copy link
Copy Markdown
Owner

@jtn0123 jtn0123 commented Apr 1, 2026

Summary

  • Move 5 mobile-specific modules into src/modules/mobile/ with barrel export
  • First domain move of the module reorganization initiative (JTN-128)
  • Re-export shims at old paths ensure zero breakage for tests and indirect consumers
  • script.ts updated to import from mobile/index.ts barrel

Files moved

  • mobile-nav.tsmobile/mobile-nav.ts
  • mobile-filters.tsmobile/mobile-filters.ts
  • mobile-filter-logic.tsmobile/mobile-filter-logic.ts
  • mobile-filter-sheet.tsmobile/mobile-filter-sheet.ts
  • pull-refresh.tsmobile/pull-refresh.ts

Test plan

  • npm run lint — 0 errors
  • npm run build — succeeds, bundle size unchanged
  • npx vitest run — 244 test files, 10,034 tests pass
  • Shims at old paths ensure test imports still work

Part of JTN-128 (Phase 2: Reorganize modules into domain directories)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor
    • Reorganized mobile module structure by consolidating mobile-related functionality into a dedicated mobile/ subdirectory for improved code organization and maintainability.

First domain move of the module reorganization initiative. Moves 5
mobile-specific modules into src/modules/mobile/ with a barrel export:
- mobile-nav.ts
- mobile-filters.ts
- mobile-filter-logic.ts
- mobile-filter-sheet.ts
- pull-refresh.ts

Re-export shims left at old paths for backwards compatibility with
tests and any indirect consumers. script.ts updated to import from
the new mobile/ barrel.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 1, 2026

📝 Walkthrough

Walkthrough

This PR reorganizes mobile-related modules by moving implementations from src/modules/ into a dedicated src/modules/mobile/ subdirectory. Original modules are replaced with re-export shims, and a new barrel module consolidates exports for cleaner imports. No functional changes—code is relocated, not modified.

Changes

Cohort / File(s) Summary
Re-export shims
src/modules/mobile-filter-logic.ts, src/modules/mobile-filter-sheet.ts, src/modules/mobile-filters.ts, src/modules/mobile-nav.ts, src/modules/pull-refresh.ts
Original implementations removed; files now delegate all exports and behavior to corresponding modules under src/modules/mobile/.
Mobile module implementations
src/modules/mobile/mobile-filter-logic.ts, src/modules/mobile/mobile-filter-sheet.ts, src/modules/mobile/mobile-filters.ts, src/modules/mobile/mobile-nav.ts, src/modules/mobile/pull-refresh.ts
New modules containing the relocated code for filter synchronization, filter sheet UI/DOM, filter controls, navigation drawer, and pull-to-refresh functionality.
Mobile barrel index
src/modules/mobile/index.ts
New file aggregating and re-exporting all mobile functionality (nav controls, filter APIs, pull-refresh, filter-sheet helpers, and filter-logic functions) for consolidated imports.
Import updates
src/script.ts
Mobile module initialization imports now sourced from src/modules/mobile/index.ts instead of individual module paths.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 Code hops into folders new,
Mobile magic bundled true,
Shims redirect the old to way,
Organization saves the day!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'refactor: move mobile modules into domain directory' is clear, specific, and accurately summarizes the main change—reorganizing mobile-specific modules into a domain directory.
Description check ✅ Passed The description covers all key aspects: a summary of the refactoring, the list of files moved, test plan results confirming no breakage, and context on the broader initiative (JTN-128).
Docstring Coverage ✅ Passed Docstring coverage is 93.18% which is sufficient. The required threshold is 80.00%.

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

✨ 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 jtn-128-move-mobile-domain

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

❤️ Share

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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 1, 2026

🚀 Preview deployed: https://537c40d2.megabonk.pages.dev

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 1, 2026

🤖 CI Summary

Job Status
Unit Tests ✅ success
Lint ✅ success
Build ✅ success
E2E Tests ✅ success

📦 Bundle Size

Main JS: 50KB

📋 What to do if tests fail?
  • Unit Tests: Check the test output in the Actions tab
  • Lint: Run npm run lint locally
  • E2E Tests: Check Playwright report artifacts
  • Skipped jobs: Path filters detected no relevant changes

Updated: 2026-04-01T13:51:14.099Z

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 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/modules/mobile/mobile-filter-logic.ts`:
- Around line 79-84: The Clear All logic sets every HTMLSelectElement to 'all',
which fails for selects like the sortBy controls whose defaults are "name" or
"date_desc" and causes applyFiltersFromSheet() to write empty/invalid values and
countActiveFilters() to treat them as active; update the sheetInputs.forEach
handling in mobile-filter-logic.ts so that for each HTMLSelectElement you either
set it to its known default (e.g., for controls named "sortBy" use "name" or
"date_desc" as appropriate) or only set it to 'all' if that option actually
exists, otherwise skip changing that select; ensure this logic references the
select's name/id to detect sortBy controls and leaves selects unchanged when the
target option is missing so applyFiltersFromSheet() and countActiveFilters()
receive valid values.

In `@src/modules/mobile/mobile-filters.ts`:
- Around line 282-291: The filter toggle's aria-expanded is only toggled in the
click handler; update both showFilterSheet() and hideFilterSheet() to explicitly
set the trigger button's aria-expanded to "true" when opening and "false" when
closing (find the same trigger element used by the click handler—the button
whose handler sets aria-expanded currently), so that
showFilterSheet()/hideFilterSheet() (and the other close paths that call
hideFilterSheet()) keep the trigger state consistent; also apply the same
aria-expanded-fix where showFilterSheet/hideFilterSheet are duplicated (the
other block referenced around lines 348-350).

In `@src/modules/mobile/mobile-nav.ts`:
- Around line 441-444: The subscribe('currentTab', ...) call in initMobileNav is
leaking because its unsubscribe function is discarded; change initMobileNav to
store the returned unsubscribe (e.g., module-level variable like
unsubscribeCurrentTab) and call it before re-subscribing or in a new exported
cleanupMobileNav() function; ensure updateMobileNavState remains the callback
and that cleanupMobileNav() (or calling the stored unsubscribe) is invoked when
tearing down or before re-initializing to avoid accumulated subscriptions.

In `@src/modules/mobile/pull-refresh.ts`:
- Around line 327-332: The review points out that assigning initPullRefresh and
cleanupPullRefresh onto globalThis unintentionally expands the public API
surface; either remove the globalThis assignment or make the export explicit and
documented. Locate the global assignment block that references globalThis and
the functions initPullRefresh and cleanupPullRefresh and: if these functions are
not meant for external consumers, delete the Object.assign(globalThis, {...})
line and rely on module exports only; if they are intended to be public, keep
the assignment but add a clear stability/version doc comment above it (e.g.,
marking it experimental/semver-stable and linking to docs), or gate the
assignment behind a feature flag (e.g., a deliberate opt-in config) so the
global export is intentional and documented.
- Around line 234-272: The call to loadAllData from triggerRefresh can run
concurrently with other callers; add concurrency protection inside the
loadAllData implementation by introducing a shared in-flight guard (e.g., an
isLoading boolean or a single Promise cache) in the data-service's loadAllData
function so that if a load is already running it either returns the existing
Promise or exits early; ensure the guard is set at the start of loadAllData,
cleared on both success and failure, and that callers like triggerRefresh
continue to await the returned Promise so state updates are serialized.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 97255663-e75c-4f15-8075-56e0e1d8168e

📥 Commits

Reviewing files that changed from the base of the PR and between bda43f2 and 0bdae2c.

📒 Files selected for processing (12)
  • src/modules/mobile-filter-logic.ts
  • src/modules/mobile-filter-sheet.ts
  • src/modules/mobile-filters.ts
  • src/modules/mobile-nav.ts
  • src/modules/mobile/index.ts
  • src/modules/mobile/mobile-filter-logic.ts
  • src/modules/mobile/mobile-filter-sheet.ts
  • src/modules/mobile/mobile-filters.ts
  • src/modules/mobile/mobile-nav.ts
  • src/modules/mobile/pull-refresh.ts
  • src/modules/pull-refresh.ts
  • src/script.ts

Comment on lines +79 to +84
sheetInputs.forEach(sheetInput => {
if (sheetInput instanceof HTMLInputElement && sheetInput.type === 'checkbox') {
sheetInput.checked = false;
} else if (sheetInput instanceof HTMLSelectElement) {
sheetInput.value = 'all';
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Don't reset every select to all.

Line 83 assumes every sheet select has an "all" option, but src/modules/mobile/mobile-filters.ts:76-83 and src/modules/mobile/mobile-filters.ts:207-212 define sortBy controls whose defaults are "name" and "date_desc". Hitting Clear All on those tabs leaves the sheet select with no matching option, and applyFiltersFromSheet() then writes an empty value back into the main filters. That empty value is also treated as active by countActiveFilters().

Suggested fix
     sheetInputs.forEach(sheetInput => {
         if (sheetInput instanceof HTMLInputElement && sheetInput.type === 'checkbox') {
             sheetInput.checked = false;
         } else if (sheetInput instanceof HTMLSelectElement) {
-            sheetInput.value = 'all';
+            sheetInput.value = sheetInput.options[0]?.value ?? '';
         }
     });
📝 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
sheetInputs.forEach(sheetInput => {
if (sheetInput instanceof HTMLInputElement && sheetInput.type === 'checkbox') {
sheetInput.checked = false;
} else if (sheetInput instanceof HTMLSelectElement) {
sheetInput.value = 'all';
}
sheetInputs.forEach(sheetInput => {
if (sheetInput instanceof HTMLInputElement && sheetInput.type === 'checkbox') {
sheetInput.checked = false;
} else if (sheetInput instanceof HTMLSelectElement) {
sheetInput.value = sheetInput.options[0]?.value ?? '';
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/mobile/mobile-filter-logic.ts` around lines 79 - 84, The Clear
All logic sets every HTMLSelectElement to 'all', which fails for selects like
the sortBy controls whose defaults are "name" or "date_desc" and causes
applyFiltersFromSheet() to write empty/invalid values and countActiveFilters()
to treat them as active; update the sheetInputs.forEach handling in
mobile-filter-logic.ts so that for each HTMLSelectElement you either set it to
its known default (e.g., for controls named "sortBy" use "name" or "date_desc"
as appropriate) or only set it to 'all' if that option actually exists,
otherwise skip changing that select; ensure this logic references the select's
name/id to detect sortBy controls and leaves selects unchanged when the target
option is missing so applyFiltersFromSheet() and countActiveFilters() receive
valid values.

Comment on lines +282 to +291
export function hideFilterSheet(): void {
const sheet = safeGetElementById('filter-bottom-sheet');
if (!sheet) return;

isSheetOpen = false;
sheet.classList.remove('active');
document.body.classList.remove('filter-sheet-open');

document.removeEventListener('keydown', _handleKeyboardNavigation);
document.removeEventListener('keydown', _handleFocusTrap);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Keep the trigger's aria-expanded state in showFilterSheet()/hideFilterSheet().

aria-expanded is only updated in the trigger's click handler right now. Backdrop, close button, Apply, and Escape all close the sheet through hideFilterSheet() (src/modules/mobile/mobile-filter-sheet.ts:97-111 and src/modules/mobile/mobile-filter-sheet.ts:121-123), so the Filters button can keep announcing itself as expanded after the dialog is already closed.

Suggested fix
 export function showFilterSheet(): void {
     previouslyFocusedElement = document.activeElement as HTMLElement;
@@
     isSheetOpen = true;
+    safeQuerySelector('.mobile-filter-btn')?.setAttribute('aria-expanded', 'true');
     sheet.classList.add('active');
     document.body.classList.add('filter-sheet-open');
@@
 export function hideFilterSheet(): void {
     const sheet = safeGetElementById('filter-bottom-sheet');
     if (!sheet) return;

     isSheetOpen = false;
+    safeQuerySelector('.mobile-filter-btn')?.setAttribute('aria-expanded', 'false');
     sheet.classList.remove('active');
     document.body.classList.remove('filter-sheet-open');
@@
     btn.addEventListener('click', () => {
         toggleFilterSheet();
-        btn.setAttribute('aria-expanded', isSheetOpen ? 'true' : 'false');
     });

Also applies to: 348-350

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

In `@src/modules/mobile/mobile-filters.ts` around lines 282 - 291, The filter
toggle's aria-expanded is only toggled in the click handler; update both
showFilterSheet() and hideFilterSheet() to explicitly set the trigger button's
aria-expanded to "true" when opening and "false" when closing (find the same
trigger element used by the click handler—the button whose handler sets
aria-expanded currently), so that showFilterSheet()/hideFilterSheet() (and the
other close paths that call hideFilterSheet()) keep the trigger state
consistent; also apply the same aria-expanded-fix where
showFilterSheet/hideFilterSheet are duplicated (the other block referenced
around lines 348-350).

Comment on lines +441 to +444
// Subscribe to tab changes to update nav state
subscribe('currentTab', newTab => {
updateMobileNavState(newTab as string);
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Memory leak: subscribe() return value is discarded.

The subscribe('currentTab', ...) call returns an unsubscribe function that's never stored. If initMobileNav() is called multiple times (e.g., during hot module replacement or test setup), subscriptions accumulate and callbacks persist indefinitely.

Proposed fix: Store and call unsubscribe on cleanup

Add module-level unsubscribe tracking:

+let unsubscribeCurrentTab: (() => void) | null = null;
+
 export function initMobileNav(): void {
     const mobileNav = safeQuerySelector('.mobile-bottom-nav');
     // ...
 
     // Subscribe to tab changes to update nav state
-    subscribe('currentTab', newTab => {
+    // Clean up any existing subscription first
+    unsubscribeCurrentTab?.();
+    unsubscribeCurrentTab = subscribe('currentTab', newTab => {
         updateMobileNavState(newTab as string);
     });

Optionally, export a cleanupMobileNav() function for symmetry with other mobile modules.

📝 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
// Subscribe to tab changes to update nav state
subscribe('currentTab', newTab => {
updateMobileNavState(newTab as string);
});
let unsubscribeCurrentTab: (() => void) | null = null;
export function initMobileNav(): void {
const mobileNav = safeQuerySelector('.mobile-bottom-nav');
// ... other initialization code ...
// Subscribe to tab changes to update nav state
// Clean up any existing subscription first
unsubscribeCurrentTab?.();
unsubscribeCurrentTab = subscribe('currentTab', newTab => {
updateMobileNavState(newTab as string);
});
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/mobile/mobile-nav.ts` around lines 441 - 444, The
subscribe('currentTab', ...) call in initMobileNav is leaking because its
unsubscribe function is discarded; change initMobileNav to store the returned
unsubscribe (e.g., module-level variable like unsubscribeCurrentTab) and call it
before re-subscribing or in a new exported cleanupMobileNav() function; ensure
updateMobileNavState remains the callback and that cleanupMobileNav() (or
calling the stored unsubscribe) is invoked when tearing down or before
re-initializing to avoid accumulated subscriptions.

Comment on lines +234 to +272
async function triggerRefresh(): Promise<void> {
state.isRefreshing = true;
updateIndicator(PULL_REFRESH_CONFIG.PULL_THRESHOLD, true);

logger.info({
operation: 'pull-refresh.triggered',
data: { source: 'touch-gesture' },
});

const startTime = performance.now();

try {
await loadAllData();

const duration = Math.round(performance.now() - startTime);
logger.info({
operation: 'pull-refresh.complete',
durationMs: duration,
success: true,
});

ToastManager.success('Data refreshed!');
} catch (error) {
const err = error as Error;
logger.error({
operation: 'pull-refresh.failed',
error: {
name: err.name,
message: err.message,
module: 'pull-refresh',
},
});
ToastManager.error('Failed to refresh data');
} finally {
state.isRefreshing = false;
state.lastRefreshTime = Date.now();
resetIndicator();
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for any mutex, lock, or in-progress flag in loadAllData
rg -n -B5 -A20 'export async function loadAllData' --type=ts

Repository: jtn0123/MegaBonk

Length of output: 1885


🏁 Script executed:

# Get the full loadAllData function to check for concurrency guards
sed -n '374,534p' src/modules/data-service.ts

Repository: jtn0123/MegaBonk

Length of output: 6886


🏁 Script executed:

# Find all calls to loadAllData to understand call patterns
rg -n 'loadAllData\(' --type=ts -B2 -A2 | head -80

Repository: jtn0123/MegaBonk

Length of output: 4373


🏁 Script executed:

# Find setState implementation to check for concurrent call safety
rg -n 'function setState|export.*setState' --type=ts -A10 | head -60

Repository: jtn0123/MegaBonk

Length of output: 2002


Race condition: loadAllData() lacks concurrent call protection.

The triggerRefresh() function calls loadAllData() without checking if another load is already in progress. The function can be invoked from multiple sources: initial page load (script.ts), offline UI retry (offline-ui.ts), pull-to-refresh (pull-refresh.ts), and error recovery (events-core.ts).

Since loadAllData() has no mutex or in-progress flag, concurrent calls can interleave setState() operations, corrupting app state. The local isRefreshing flag only prevents double-triggers within pull-refresh itself, not cross-module concurrent calls.

Add a guard in data-service.ts to prevent concurrent loads—either check a shared isLoading flag before proceeding, or return the existing promise if a load is already in flight.

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

In `@src/modules/mobile/pull-refresh.ts` around lines 234 - 272, The call to
loadAllData from triggerRefresh can run concurrently with other callers; add
concurrency protection inside the loadAllData implementation by introducing a
shared in-flight guard (e.g., an isLoading boolean or a single Promise cache) in
the data-service's loadAllData function so that if a load is already running it
either returns the existing Promise or exits early; ensure the guard is set at
the start of loadAllData, cleared on both success and failure, and that callers
like triggerRefresh continue to await the returned Promise so state updates are
serialized.

Comment on lines +327 to +332
if (typeof globalThis !== 'undefined') {
Object.assign(globalThis, {
initPullRefresh,
cleanupPullRefresh,
});
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider documenting API stability for globalThis exports.

Assigning initPullRefresh and cleanupPullRefresh to globalThis exposes them for external scripts, but there's no versioning or stability contract. If these are intended for external consumption, consider documenting them; otherwise, consider removing the global assignment to reduce API surface.

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

In `@src/modules/mobile/pull-refresh.ts` around lines 327 - 332, The review points
out that assigning initPullRefresh and cleanupPullRefresh onto globalThis
unintentionally expands the public API surface; either remove the globalThis
assignment or make the export explicit and documented. Locate the global
assignment block that references globalThis and the functions initPullRefresh
and cleanupPullRefresh and: if these functions are not meant for external
consumers, delete the Object.assign(globalThis, {...}) line and rely on module
exports only; if they are intended to be public, keep the assignment but add a
clear stability/version doc comment above it (e.g., marking it
experimental/semver-stable and linking to docs), or gate the assignment behind a
feature flag (e.g., a deliberate opt-in config) so the global export is
intentional and documented.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Apr 1, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
74.0% Coverage on New Code (required ≥ 80%)
10.4% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 1, 2026

❌ SonarCloud Analysis

Quality Gate Coverage Bugs Vulnerabilities Code Smells Duplications

Quality Gate: Failed

New Code

Metric Value
🐛 Bugs N/A
🔓 Vulnerabilities N/A
🔥 Security Hotspots N/A
🧹 Code Smells N/A
📊 Coverage NaN%
📋 Duplication NaN%
🕐 New Debt N/A

Ratings

Reliability Security Maintainability
Grade N/A N/A N/A

Files Changed

File Coverage Lines
src/modules/mobile/index.ts N/A 23
src/modules/mobile-filter-logic.ts N/A 1
src/modules/mobile-filter-sheet.ts N/A 2
src/modules/mobile-filters.ts N/A 1
src/modules/mobile-nav.ts N/A 1
src/modules/pull-refresh.ts N/A 1
src/script.ts 0.0% 308
⚠️ src/modules/mobile/mobile-nav.ts 53.5% 297
⚠️ src/modules/mobile/mobile-filters.ts 71.6% 325
⚠️ src/modules/mobile/mobile-filter-sheet.ts 75.0% 112
src/modules/mobile/mobile-filter-logic.ts 90.5% 83
src/modules/mobile/pull-refresh.ts 97.5% 212

Issues (1 found)

🧹 1 Code Smell
Type Severity File Description
🧹 CRITICAL src/modules/mobile/mobile-nav.ts:353 Refactor this function to reduce its Cognitive Complexity from 19 to the 15 allowed.

Overall Project

Metric Value
📊 Coverage 77.2% (→ 0.0% from previous)
🕐 Technical Debt 1d 5h
📏 Lines of Code 47319
🐛 Bugs 0
🔓 Vulnerabilities 0
🧹 Code Smells 369
📋 Duplication 0.6%

View full analysis on SonarCloud


SonarCloud · 1a2ec46 · 2026-04-01 13:52:28 UTC

const isMoreTab = MORE_TAB_NAMES.has(currentTab);
const currentMoreTab = isMoreTab ? MORE_MENU_TABS.find(t => t.tab === currentTab) : null;

navItems.forEach(item => {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 SonarCloud CRITICAL: Refactor this function to reduce its Cognitive Complexity from 19 to the 15 allowed.

View in SonarCloud

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 2, 2026

This PR has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs.

@github-actions github-actions Bot added the Stale label May 2, 2026
@github-actions github-actions Bot closed this May 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant