Skip to content

refactor(ui): flatten nested ternaries in apps/mobile (Sonar typescript:S3358) - #484

Merged
thomasluizon merged 2 commits into
mainfrom
chore/sonar-s3358-mobile
Jul 13, 2026
Merged

refactor(ui): flatten nested ternaries in apps/mobile (Sonar typescript:S3358)#484
thomasluizon merged 2 commits into
mainfrom
chore/sonar-s3358-mobile

Conversation

@thomasluizon

Copy link
Copy Markdown
Owner

What

Flattens every nested conditional expression flagged by SonarCloud rule typescript:S3358 (Extract this nested ternary operation into an independent statement) that is scoped to apps/mobile44 files / 59 instances.

apps/web + packages/shared S3358 instances are handled by a sibling slice, so cross-platform parity is preserved at the batch level.

How (behavior- and render-preserving)

Each nested ternary was removed with the smallest structural change that keeps rendered output identical:

  • Value chains → extract the inner ternary into a preceding named const (or an if/else helper for 3+ levels), leaving only single-level ternaries.
  • Style-callback nested ternaries → convert the arrow to a block body and hoist the inner ternary into a local const.
  • cond ? (inner) : null in JSX/style arrays → cond && (inner) (falsy is ignored identically), used only where the discarded branch is null/falsy and the guard is a boolean.
  • Multi-state JSX chains (loading/error/empty/content) → hoist into a let x: ReactNode computed with if/else if before return, rendered as {x}.

No any, no narration comments, no i18n or logic changes.

Verification

  • npx tsc --noEmit — clean
  • npx vitest run1056 passed (200 files)
  • npx expo lint0 errors (1 pre-existing warning in untouched calendar-sync.tsx)
  • react-doctor --blocking error --scope changed0 blocking errors
  • jscpd at Sonar's 10-line threshold — 0 new cross-file clones among the refactored files

Refs #243

…pt:S3358)

Extract nested conditional expressions into named consts, if/else
assignments, and hoisted ReactNode variables so no ternary is nested
inside another. Behavior- and render-preserving across all 44 files /
59 S3358 instances scoped to apps/mobile.

apps/web + packages/shared S3358 instances are handled by a sibling
slice, so parity is preserved at the batch level.

Refs #243

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
orbit-ui-mobile-web Ignored Ignored Jul 13, 2026 1:38pm

Request Review

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

Code Review: PR #484 — refactor(ui): flatten nested ternaries in apps/mobile (Sonar typescript:S3358)

Scope: PR #484 in thomasluizon/orbit-ui-mobile (44 files, 59 nested-ternary instances flattened)
Recommendation: APPROVE

Summary

This is a pure, mechanical, behavior-preserving refactor that eliminates every SonarCloud typescript:S3358 (nested ternary) instance scoped to apps/mobile. Each transform is one of four small, well-understood patterns (hoist inner ternary to a named const, convert to an if/else block before return, cond ? X : nullcond && X where the guard is boolean/nullable-object, or multi-branch JSX chains hoisted into a let x: ReactNode variable). I walked all 44 changed files diff-hunk by diff-hunk and traced every extracted variable/branch back to the original ternary to confirm identical runtime behavior. No logic, styling, token, or i18n-key changes were found.

Findings

Critical

None.

High

None.

Medium

None.

Low / Info

  • Info: A few of the cond && (...) conversions (apps/mobile/app/(tabs)/calendar.tsx:9-30, apps/mobile/app/accountability-pair.tsx:378, apps/mobile/components/goal-card.tsx:1134) rely on the guard being a strict boolean or a nullable object rather than a number/string, which is the classic React "renders a stray 0" footgun for this pattern. Verified each guard's type (activeError/rangeError are query-error objects, isPending/isSelectMode are booleans, trackingDot is {...} | null) — none can be a falsy-but-truthy-rendering primitive, so this is not a live bug, just worth naming as the one thing this transform class needs to keep checking each time it's applied.

Subagents

Agent Verdict
parity-checker PAIRED — see note below (checked manually, not delegated)
i18n-syncer N/A — no i18n keys added, removed, or renamed; every t(...) call in the diff is a pre-existing key relocated verbatim into the new if/const structure
contract-aligner N/A — no packages/shared/src/types/* or endpoints.ts touched
security-reviewer N/A — no orbit-api code in this diff
design-reviewer PASS — confirmed every color/style computation still resolves through the same semantic tokens as before (tokens.fg1/fg2/fg4, tintFromPrimary, tokens.primary, etc.); no new AI-slop tell, no raw --slate-*/hardcoded rgba, no em dash introduced

Parity note: this PR only touches apps/mobile. The PR body states the apps/web + packages/shared S3358 instances were fixed in a sibling PR. I confirmed this directly: PR #483 ("chore(ui): flatten nested ternaries (Sonar typescript:S3358)"), already merged to main ahead of this PR, fixes the corresponding web-side files for the same components touched here (calendar-range-view, calendar-week-view, social/*, upgrade/page, goal-card, goal-detail-drawer, edit-goal-modal, empty-state, pricing-section, habit-row-check-circle, move-parent-overlay, retrospective-dashboard, login-sections). Parity is preserved at the batch level, as claimed — not a finding.

Validation

Check Result
Lint N/A in CI review — Build/Unit Tests/SonarCloud run as separate required checks on this PR per repo CI config
Type check N/A in CI review — same as above
Tests N/A in CI review — PR body reports vitest run 1056/1056 passing (200 files) and tsc --noEmit clean; not independently re-run here
Build (api) N/A — orbit-api not touched, not checked out in this job

Deferred — N/A dimensions & files not verdicted

  • FEATURES.md parity (#14): N/A — pure refactor, no user-facing behavior change, no screen/route/tool/gating change.
  • Backend hard rules (#13): N/A — orbit-api not touched.
  • Contract drift (#11): N/A — no shared-type or DTO surface touched.
  • i18n (#10): N/A — no string/key changes (see Subagents).
  • Validation (Lint/Type/Test): not run in this session — per this repo's CI wrapper instructions, Build/Unit Tests/SonarCloud already run as separate required checks on this PR, so re-running here would be redundant.
  • Cross-repo dimensions requiring orbit-api: not verifiable in this job (sibling repo not checked out).
  • Every one of the 44 changed files got an explicit verdict (traced against its pre-refactor version) — nothing in the diff was skipped.

What's good

  • Every single-variable extraction and if/else chain is traceable 1:1 back to the original ternary's branch order and condition — zero behavior drift found across 59 instances.
  • No any, no console.log, no new comments (narration or otherwise) introduced anywhere in the diff — clean on rules 3, 4, and 5.
  • The PR body is unusually thorough: it names the four transform patterns used, discloses the sibling-PR split for parity, and reports its own verification commands (tsc, vitest, expo lint, react-doctor, jscpd) with actual output — exactly the kind of self-auditing a pure mechanical refactor should ship with.
  • Correctly resisted the temptation to "clean up while here" — no drive-by logic changes riding along with the Sonar fix.

Recommendation

Approve as-is. This PR does exactly what it says, nothing more, and every transformation checks out against the original code.

@thomasluizon

Copy link
Copy Markdown
Owner Author

CI status — ready to merge (SonarCloud coverage-only override)

All required checks pass. The only red is SonarCloud → new_coverage 0.0% (< 80%), which needs an admin override at merge.

SonarCloud PR quality-gate conditions:

Condition Status Actual Threshold
new_reliability_rating ✅ OK 1 (A) 1
new_security_rating ✅ OK 1 (A) 1
new_maintainability_rating ✅ OK 1 (A) 1
new_duplicated_lines_density ✅ OK 0.0% 3%
new_security_hotspots_reviewed ✅ OK 100% 100%
new_coverage ❌ ERROR 0.0% 80%
  • typescript:S3358 on this PR: 0 (all 59 apps/mobile instances across 44 files resolved).
  • No new smells, bugs, security issues, or duplication — the flattening is behavior- and render-preserving (extracted nested ternaries into named consts / if/else assignments / hoisted ReactNode variables).
  • The 0% new-code coverage is expected: the touched files are presentational React Native components with no unit tests, and a behavior-preserving refactor adds no new covered lines. Full mobile suite stays green (1056 tests passing).

The transient Lint / Type Check / Contract Drift / Dependency Audit reds were a GitHub Actions action-resolution outage ("Failed to resolve action download info") and all pass on re-run.

@thomasluizon
thomasluizon merged commit 5f01a0b into main Jul 13, 2026
1 check passed
@thomasluizon
thomasluizon deleted the chore/sonar-s3358-mobile branch July 13, 2026 13:39
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

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

/pr-review — PR #484

Scope: refactor(ui): flatten nested ternaries in apps/mobile (Sonar typescript:S3358) — 44 files, 59 instances.

No diff since last review. This bot already posted an APPROVE on this exact head commit (04615549629166bc74b8f5873c811a93e8c1747f) at 2026-07-13T13:32:19Z. gh pr view 484 confirms headRefOid is byte-identical and the PR is now MERGED — zero new commits, zero new hunks since that review. Re-walking the full rubric would just reproduce the prior pass verbatim.

Recommendation: APPROVE (carried forward, unchanged)

Severity Count
Critical 0
High 0
Medium 0
Low / Info 1 (carried forward — cond && (...) guard-type pattern noted, assessed as not a live bug)

Findings, still valid at the current head:

  • Pure, mechanical, behavior-preserving refactor; all 44 files traced 1:1 against pre-refactor ternary logic.
  • No any, no console.log, no new comments introduced; no i18n or logic changes.
  • Parity: corresponding apps/web / packages/shared S3358 instances were handled in the already-merged sibling PR #483 — confirmed directly.
  • No packages/shared or orbit-api surface touched → contract-drift and backward-compat-guard dimensions are not applicable; cross-repo dimensions requiring the orbit-api checkout are not verifiable in this CI job but are also not triggered by this diff.
  • Validation (lint/type-check/tests) intentionally not re-run — owned by CI's Build / Unit Tests / SonarCloud required checks per this workflow's scope.

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.

1 participant