Skip to content

Conversation

@AhmedCodeGuy
Copy link
Collaborator

@AhmedCodeGuy AhmedCodeGuy commented Nov 18, 2025

Problem

Closes: QF-3857

The "Explore Answers" button was not appearing for verses with questions in both Translation View and Reading View.

Root Cause

The API returns questions data with this structure:

{
  "1:2": {
    "types": {
      "TAFSIR": 3,
      "COMMUNITY": 2
    },
    "total": 5
  }
}

However, the code was comparing the entire object to a number:

// ❌ Wrong - compares object to number
const hasQuestions = questionsCount[verseKey] > 0;  

This comparison always evaluated to false, preventing the button from showing.

Solution

Updated all code to correctly access the .total property:

// ✅ Correct - accesses total property
const hasQuestions = questionsCount?.[verseKey]?.total > 0;

Changes

1. Fixed Data Access (3 files)

  • QuestionsButton/index.tsx: Added .total property access with optional chaining
  • TranslationPageVerse.tsx: Added .total property access with optional chaining
  • Both now correctly check if verses have questions

2. Updated Type Definitions (3 files)

  • api.ts: Added QuestionData type export matching API response structure
  • useCountRangeQuestions.ts: Updated types from Record<string, number> to Record<string, QuestionData>
  • PageQuestionsContext.tsx: Updated context type to use QuestionData

This ensures type safety and prevents similar bugs in the future.

Testing

Verified with production API data:

  • Verse 1:2 with 5 questions → Button shows ✅
  • Verse 1:3 with 1 question → Button shows ✅
  • Verse 1:1 with 0 questions → No button ✅

Files Changed

src/components/QuranReader/ReadingView/Buttons/QuestionsButton/index.tsx
src/components/QuranReader/ReadingView/context/PageQuestionsContext.tsx
src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx
src/hooks/auth/useCountRangeQuestions.ts
src/utils/auth/api.ts

Impact

  • No breaking changes - Pure bug fix
  • No regressions - Only affects questions button visibility
  • Type safe - Prevents future bugs with proper TypeScript types
  • Backward compatible - Optional chaining handles all edge cases

Checklist

  • Code reviewed for correctness
  • Edge cases verified (null/undefined handling)
  • Type safety improved with proper TypeScript types
  • All usages of questions data updated
  • No other files need similar fixes

Summary by CodeRabbit

  • Bug Fixes

    • Enhanced question metadata validation to prevent edge cases and ensure question indicators display accurately across all reader views, particularly when handling missing or undefined data.
  • Refactor

    • Improved internal data structures and type definitions for question tracking to provide better robustness and consistent null-value handling throughout the Quran reader components.

…nData

Refactor question counting to use a new QuestionData type that includes 'total' and 'types' fields, ensuring accurate visibility of questions button and related UI elements. This fixes issues where the button wasn't showing due to outdated count checks.
@AhmedCodeGuy AhmedCodeGuy self-assigned this Nov 18, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 18, 2025

Walkthrough

The PR refactors the question counting system to replace simple numeric counts with a structured QuestionData type containing question type breakdowns and a total count. All references throughout the codebase are updated to access the total property using safe optional chaining.

Changes

Cohort / File(s) Summary
Core type definition
src/utils/auth/api.ts
Introduces new QuestionData type with types (Record<string, number>) and total (number) fields. Updates countQuestionsWithinRange return type from Promise<Record<string, number>> to Promise<Record<string, QuestionData>>.
Context and hook types
src/components/QuranReader/ReadingView/context/PageQuestionsContext.tsx, src/hooks/auth/useCountRangeQuestions.ts
Updates context and hook to use QuestionData instead of number. PageQuestionsContext type changed from Record<string, number> | undefined to Record<string, QuestionData> | undefined. CountRangeQuestionsResponse data field updated accordingly.
Component implementations
src/components/QuranReader/ReadingView/Buttons/QuestionsButton/index.tsx, src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx
Updates question existence checks to safely access nested total property: pageQuestionsCount[verseKey]?.total > 0 and questionsCount?.[verse.verseKey]?.total > 0 respectively.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • Changes follow a consistent, homogeneous pattern across all files (type signature updates + property access changes)
  • All logic modifications are straightforward safe property access using optional chaining
  • No control flow changes or complex interactions
  • Type safety is improved without altering behavior

Suggested reviewers

  • osamasayed

Poem

🐰 A question mark now holds a tale so true,
Not just a count, but types in every hue,
With .total fields and structured grace,
The questions find their proper place! 📚✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: fixing the questions button visibility issue caused by incorrect data structure access. It is concise and clearly identifies the bug being fixed.
Description check ✅ Passed The description comprehensively covers the problem, root cause, solution, changes made, testing performed, and impact assessment. It follows the template structure with clear sections and includes all critical information.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch hotfix/questions-button-not-showing

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7e2551 and fff2acf.

📒 Files selected for processing (5)
  • src/components/QuranReader/ReadingView/Buttons/QuestionsButton/index.tsx (1 hunks)
  • src/components/QuranReader/ReadingView/context/PageQuestionsContext.tsx (1 hunks)
  • src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx (1 hunks)
  • src/hooks/auth/useCountRangeQuestions.ts (2 hunks)
  • src/utils/auth/api.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (12)
**/*.*

📄 CodeRabbit inference engine (.cursor/rules/bug-handling-with-todo-comments.mdc)

If you encounter a bug in existing code, or the instructions lead to suboptimal or buggy code, add comments starting with "TODO:" outlining the problems.

**/*.*: Utilize Early Returns: Use early returns to avoid nested conditions and improve readability.
Conditional Classes: Prefer conditional classes over ternary operators for class attributes.

**/*.*: Use comments sparingly, and when you do, make them meaningful.
Don't comment on obvious things. Excessive or unclear comments can clutter the codebase and become outdated.
Use comments to convey the 'why' behind specific actions or explain unusual behavior and potential pitfalls.
Provide meaningful information about the function's behavior and explain unusual behavior and potential pitfalls.

**/*.*: Write short functions that only do one thing.
Follow the single responsibility principle (SRP), which means that a function should have one purpose and perform it effectively.
If a function becomes too long or complex, consider breaking it into smaller, more manageable functions.

Order functions with those that are composing other functions appearing earlier in the file. For example, if you have a menu with multiple buttons, define the menu function above the buttons.

**/*.*: Always add helpful comments to the code explaining what you are doing.
Never delete old comments, unless they are no longer relevant because the code has been rewritten or deleted.

**/*.*: Choose names for variables, functions, and classes that reflect their purpose and behavior.
A name should tell you why it exists, what it does, and how it is used. If a name requires a comment, then the name does not reveal its intent.
Use specific names that provide a clearer understanding of what the variables represent and how they are used.

Files:

  • src/components/QuranReader/ReadingView/context/PageQuestionsContext.tsx
  • src/utils/auth/api.ts
  • src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx
  • src/components/QuranReader/ReadingView/Buttons/QuestionsButton/index.tsx
  • src/hooks/auth/useCountRangeQuestions.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/next-js-conventions.mdc)

**/*.{js,jsx,ts,tsx}: Rely on Next.js Pages Router for state changes.
Minimize 'use client' usage: Prefer server components and Next.js SSR features.
Minimize 'use client' usage: Use 'use client' only for Web API access in small components.
Minimize 'use client' usage: Avoid using 'use client' for data fetching or state management.

**/*.{js,jsx,ts,tsx}: Optimize Web Vitals (LCP, CLS, FID)
Use dynamic loading for non-critical components using @src/components/dls/Spinner/Spinner.tsx

Files:

  • src/components/QuranReader/ReadingView/context/PageQuestionsContext.tsx
  • src/utils/auth/api.ts
  • src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx
  • src/components/QuranReader/ReadingView/Buttons/QuestionsButton/index.tsx
  • src/hooks/auth/useCountRangeQuestions.ts
src/components/**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/react-functional-components.mdc)

src/components/**/*.tsx: Always use React functional components with hooks.
Use React.FC for functional components with props.

Files:

  • src/components/QuranReader/ReadingView/context/PageQuestionsContext.tsx
  • src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx
  • src/components/QuranReader/ReadingView/Buttons/QuestionsButton/index.tsx
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

**/*.{tsx,jsx}: Use functional components over class components
Keep components small and focused
Extract reusable logic into custom hooks
Use composition over inheritance
Split large components into smaller, focused ones
Follow the Rules of Hooks
Use custom hooks for reusable logic
Use appropriate dependency arrays in useEffect
Implement cleanup in useEffect when needed
Avoid nested hooks
Use useState for local component state
Avoid prop drilling through proper state management
Implement proper memoization (useMemo, useCallback)
Use React.memo for expensive components
Avoid unnecessary re-renders
Implement proper lazy loading
Use proper key props in lists
Profile and optimize render performance
Show appropriate loading and error states
Handle async errors properly
Show user-friendly error messages
Implement proper fallback UI
Log errors appropriately
Handle edge cases gracefully
Use semantic HTML elements
Implement proper ARIA attributes
Ensure keyboard navigation
Handle focus management
Provide proper alt text for images
Use proper imports/exports
Document complex component logic

Files:

  • src/components/QuranReader/ReadingView/context/PageQuestionsContext.tsx
  • src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx
  • src/components/QuranReader/ReadingView/Buttons/QuestionsButton/index.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

Implement proper prop types with TypeScript

**/*.tsx: Prefix interfaces for React props with 'Props' (e.g., ButtonProps)
Implement proper error boundaries

Files:

  • src/components/QuranReader/ReadingView/context/PageQuestionsContext.tsx
  • src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx
  • src/components/QuranReader/ReadingView/Buttons/QuestionsButton/index.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

Use xstate for complex state logic

Files:

  • src/components/QuranReader/ReadingView/context/PageQuestionsContext.tsx
  • src/utils/auth/api.ts
  • src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx
  • src/components/QuranReader/ReadingView/Buttons/QuestionsButton/index.tsx
  • src/hooks/auth/useCountRangeQuestions.ts
**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/*.{ts,tsx,d.ts}: Prefer interfaces over types for object definitions
Use type for unions, intersections, and mapped types
Avoid using any, prefer unknown for unknown types
Leverage TypeScript's built-in utility types
Use generics for reusable type patterns
Use PascalCase for type names and interfaces
Use camelCase for variables and functions
Use UPPER_CASE for constants
Use descriptive names with auxiliary verbs (e.g., isLoading, hasError)
Use explicit return types for public functions
Use arrow functions for callbacks and methods
Implement proper error handling with custom error types
Use function overloads for complex type scenarios
Prefer async/await over Promises
Use readonly for immutable properties
Leverage discriminated unions for type safety
Use type guards for runtime type checking
Implement proper null checking
Avoid type assertions unless necessary
Create custom error types for domain-specific errors
Use Result types for operations that can fail
Use try-catch blocks with typed catch clauses
Handle Promise rejections properly

Files:

  • src/components/QuranReader/ReadingView/context/PageQuestionsContext.tsx
  • src/utils/auth/api.ts
  • src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx
  • src/components/QuranReader/ReadingView/Buttons/QuestionsButton/index.tsx
  • src/hooks/auth/useCountRangeQuestions.ts
{src,types}/**/*.ts?(x)

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript throughout the codebase with strict configuration

Files:

  • src/components/QuranReader/ReadingView/context/PageQuestionsContext.tsx
  • src/utils/auth/api.ts
  • src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx
  • src/components/QuranReader/ReadingView/Buttons/QuestionsButton/index.tsx
  • src/hooks/auth/useCountRangeQuestions.ts
src/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer React functional components for UI implementation

Files:

  • src/components/QuranReader/ReadingView/context/PageQuestionsContext.tsx
  • src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx
  • src/components/QuranReader/ReadingView/Buttons/QuestionsButton/index.tsx
{src,types}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use path aliases @/ for src and @/dls/* for design system imports

Files:

  • src/components/QuranReader/ReadingView/context/PageQuestionsContext.tsx
  • src/utils/auth/api.ts
  • src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx
  • src/components/QuranReader/ReadingView/Buttons/QuestionsButton/index.tsx
  • src/hooks/auth/useCountRangeQuestions.ts
src/components/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Organize React components by feature and place DLS components under src/components/dls

Files:

  • src/components/QuranReader/ReadingView/context/PageQuestionsContext.tsx
  • src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx
  • src/components/QuranReader/ReadingView/Buttons/QuestionsButton/index.tsx
src/utils/auth/api.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Place authentication API utilities in src/utils/auth/api.ts

Files:

  • src/utils/auth/api.ts
🧠 Learnings (2)
📚 Learning: 2025-10-26T10:22:52.381Z
Learnt from: afifvdin
Repo: quran/quran.com-frontend-next PR: 2540
File: src/components/QuranReader/TranslationView/TranslationText/TranslationAndReference.tsx:60-60
Timestamp: 2025-10-26T10:22:52.381Z
Learning: In src/components/QuranReader/TranslationView/TranslationText/TranslationAndReference.tsx, verse references displayed alongside chapter names should use English/Western numerals only, not localized numerals, as per design specifications.

Applied to files:

  • src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx
  • src/components/QuranReader/ReadingView/Buttons/QuestionsButton/index.tsx
📚 Learning: 2025-10-19T11:34:07.609Z
Learnt from: afifvdin
Repo: quran/quran.com-frontend-next PR: 2540
File: src/components/Verse/PlainVerseText/index.tsx:4-4
Timestamp: 2025-10-19T11:34:07.609Z
Learning: In src/components/Verse/PlainVerseText/index.tsx, the translation for verse titles should be wired directly to the component using next-translate rather than passed as props from parent components, as this ensures the wording from locales is centralized and only needs to be changed in one place.

Applied to files:

  • src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx
🧬 Code graph analysis (2)
src/components/QuranReader/ReadingView/context/PageQuestionsContext.tsx (1)
src/utils/auth/api.ts (1)
  • QuestionData (481-484)
src/hooks/auth/useCountRangeQuestions.ts (2)
src/utils/auth/api.ts (1)
  • QuestionData (481-484)
src/utils/auth/apiPaths.ts (1)
  • makeCountQuestionsWithinRangeUrl (115-124)
🔇 Additional comments (9)
src/components/QuranReader/ReadingView/Buttons/QuestionsButton/index.tsx (1)

27-27: LGTM! Type-safe access with optional chaining.

The change correctly accesses the nested total property using optional chaining, which safely handles cases where pageQuestionsCount or the verse entry might be undefined.

src/components/QuranReader/TranslationView/TranslationViewVerse/TranslationPageVerse.tsx (1)

107-108: LGTM! Correct nested property access with optional chaining.

Both hasQuestions and hasNotes properly use optional chaining. The difference in structure (questionsCount uses .total while notesCount is a direct number) correctly reflects the API's data shape.

src/utils/auth/api.ts (2)

481-484: LGTM! Well-structured type definition.

The QuestionData type properly captures the question count structure with both detailed type breakdown and total count. Using Record<string, number> for types provides flexibility for different question types.


486-492: LGTM! Return type updated consistently.

The function signature correctly reflects the new structured response format. The change maintains backward compatibility by keeping the verse key mapping at the top level while changing the value structure.

src/hooks/auth/useCountRangeQuestions.ts (3)

5-5: LGTM! Import aligned with API changes.

The import correctly brings in the new QuestionData type definition from the API utilities.


13-17: LGTM! Type definition updated consistently.

The response type correctly reflects the new data structure with QuestionData values while maintaining the same overall interface shape.


19-28: LGTM! SWR hook properly typed.

All generic types and return types are correctly updated to use Record<string, QuestionData>, ensuring type safety throughout the data flow.

src/components/QuranReader/ReadingView/context/PageQuestionsContext.tsx (2)

3-7: LGTM! Context type updated consistently.

The context type correctly reflects the new QuestionData structure, maintaining consistency with the API and hook types throughout the codebase.


9-12: LGTM! Safe fallback handling.

The hook properly returns an empty object when context is undefined, which works correctly with the optional chaining used in consuming components (e.g., pageQuestionsCount?.[verseKey]?.total).


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.

@osamasayed osamasayed requested a review from Copilot November 18, 2025 09:17
Copilot finished reviewing on behalf of osamasayed November 18, 2025 09:20
Copy link
Contributor

Copilot AI left a comment

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 fixes a bug where the "Explore Answers" button was not appearing for verses with questions. The root cause was that the code was comparing the entire QuestionData object (containing types and total properties) to a number, which always evaluated to false.

Key Changes:

  • Updated data access patterns to correctly access the .total property of QuestionData objects with optional chaining
  • Added QuestionData type definition and updated all related type signatures throughout the codebase
  • Fixed button visibility logic in both Reading View and Translation View

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
api.ts Added QuestionData type export and updated return type for countQuestionsWithinRange function
useCountRangeQuestions.ts Updated all type signatures to use Record<string, QuestionData> instead of Record<string, number>
PageQuestionsContext.tsx Updated context type to use QuestionData for type safety
TranslationPageVerse.tsx Fixed questions check to access .total property with optional chaining
QuestionsButton/index.tsx Fixed questions check to access .total property with optional chaining

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

@osamasayed osamasayed changed the base branch from production to testing November 19, 2025 02:13
@osamasayed osamasayed changed the base branch from testing to production November 19, 2025 02:13
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