Skip to content

Conversation

@yousefdergham
Copy link
Collaborator

@yousefdergham yousefdergham commented Nov 18, 2025

Summary

Fixes QF-3520

This PR removes guest enrollment functionality and implements enrollment method tracking to align with backend changes in quran/quran.com-users-backend#798.

Key Changes:

  • Removed guest enrollment infrastructure (Redux store, slice, hooks, CSS, and tests)
  • Added EnrollmentMethod enum with MANUAL and AUTOMATIC values
  • Implemented automatic enrollment when logged-in users view lessons
  • Updated manual enrollment to track enrollment method when users click "Start here" button
  • Created useEnrollUser hook for consistent enrollment handling

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Changes Made

1. Guest Enrollment Removal

Deleted Files:

  • src/hooks/auth/useGuestEnrollment.ts - Removed guest enrollment hooks (useIsEnrolled, useEnrollGuest)
  • src/redux/slices/guestEnrollment.ts - Removed guest enrollment Redux slice
  • tests/integration/learning-plans/guest-access.spec.ts - Removed guest access integration tests

Modified Files:

  • src/redux/store.ts - Removed guestEnrollment from store configuration and persist whitelist
  • src/redux/types/SliceName.ts - Removed GUEST_ENROLLMENT enum value
  • src/components/Course/CourseDetails/Tabs/Syllabus/Syllabus.module.scss - Removed .notEnrolledLink CSS styles

2. Enrollment Method Tracking

New Files:

  • types/auth/EnrollmentMethod.ts - Enum for enrollment method tracking
    enum EnrollmentMethod {
      Manual = 'MANUAL',
      Automatic = 'AUTOMATIC',
    }
  • src/hooks/auth/useEnrollUser.ts - New hook for enrolling logged-in users with enrollment method

Updated Components:

src/components/Course/LessonContent/index.tsx

  • Added automatic enrollment when logged-in users view lessons
  • Uses EnrollmentMethod.Automatic for auto-enrollment
  • Removed NotEnrolledNotice component (no longer needed)

src/components/Course/CourseDetails/StatusHeader/index.tsx

  • Renamed "Enroll" button to "Start here" for better UX
  • Updated to use useEnrollUser hook with EnrollmentMethod.Manual
  • Simplified enrollment flow for both logged-in and guest users
  • Guest users with allowGuestAccess can now directly access lessons without enrollment

src/components/Course/Buttons/StartOrContinueLearning/index.tsx

  • Simplified to only show "Continue Learning" button
  • Removed "Start Learning" vs "Continue Learning" logic

src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx

  • Removed enrollment checks - all lessons are now clickable
  • Removed toast notifications for non-enrolled users

3. API Integration

src/utils/auth/api.ts

  • Updated enrollUser function signature to accept enrollmentMethod parameter
  • Now sends enrollmentMethod to backend API

Before:

enrollUser(courseId: string)

After:

enrollUser({
  courseId: string;
  enrollmentMethod: EnrollmentMethod;
})

4. Localization

locales/en/learn.json

  • Added "start-here": "Start here" translation key

Test plan

Manual Testing

  • Logged-in users are automatically enrolled when viewing lessons
  • "Start here" button works for non-enrolled users
  • Guest users can access lessons directly (for courses with allowGuestAccess)
  • Syllabus lessons are clickable without enrollment checks
  • "Continue Learning" button navigates to correct lesson
  • No console errors or TypeScript errors

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • My changes generate no new warnings
  • Any dependent changes have been merged and published in downstream modules
  • I have commented on my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Dependencies

⚠️ This PR depends on backend PR: quran/quran.com-users-backend#798

The backend must be deployed first, as it adds the required enrollmentMethod field to the /courses/enroll API endpoint.

Breaking Changes

Guest Enrollment Removed:

  • Guest users can no longer "enroll" in courses via localStorage
  • Courses with allowGuestAccess flag allow guests to view content without enrollment
  • Other courses require login to access

API Changes:

  • Frontend now sends enrollmentMethod field with enrollment requests
  • Aligns with backend API changes requiring this field

Migration Notes

Redux Persist:

  • The guestEnrollment slice has been removed from Redux store
  • Users' browsers will automatically clean up the old slice on next load
  • No manual migration required

User Experience Changes

Scenario Before After
Guest viewing lesson Required "enrollment" via localStorage, shown enrollment prompts Automatically redirected to login (unless allowGuestAccess is enabled)
Logged-in user viewing lesson Required manual enrollment first Automatically enrolled on first lesson view
Enrollment button Labeled "Enroll" Labeled "Start here"
Syllabus links Blocked with toast for non-enrolled Always clickable
Start/Continue Learning Two separate buttons based on progress Single "Continue Learning" button

Summary by CodeRabbit

  • New Features

    • Automatic enrollment trigger when accessing lesson pages
  • Refactor

    • Unified Start/Continue into a single continue flow and a dedicated "Start here" enroll path
    • Removed guest-specific enrollment gating so lessons and syllabus link directly to content
  • Localization

    • Added "Start here" CTA; updated learning-plan CTA to "Start Now"
  • Style

    • Simplified not-enrolled styling; removed minimum-height constraint
  • Tests

    • Updated guest-access integration tests and helpers to match new flows

✏️ Tip: You can customize this high-level summary in your review settings.

…updating enrollUser function to accept enrollment method as a parameter.
…, updating components to utilize it, and simplifying the enrollment process for logged-in users. Adjusted StartOrContinueLearning and StatusHeader components to streamline user experience and removed unnecessary checks for enrollment status.
…the NotEnrolledNotice component along with its associated styles, streamlining the course enrollment experience.
@yousefdergham yousefdergham changed the title Qf 3518 open learning plans [QF-3518] open learning plans for guest users Nov 18, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 18, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Replaces guest-enrollment flow with a unified enroll-user approach (new hook and EnrollmentMethod), removes guest enrollment Redux slice and NotEnrolledNotice, updates components/pages to use manual/automatic enrollment or redirect unauthenticated users, adds "start-here" localization and updates a CTA label.

Changes

Cohort / File(s) Summary
Localization
locales/en/learn.json, locales/en/quran-reader.json
Added "start-here": "Start here" and changed a CTA label from "Begin Now" → "Start Now".
New enrollment hook
src/hooks/auth/useEnrollUser.ts
Added useEnrollUser hook returning an enroll function that checks login, calls the enroll API with an EnrollmentMethod, and logs errors to Sentry.
Removed guest enrollment hooks
src/hooks/auth/useGuestEnrollment.ts
Deleted guest enrollment hooks (useIsEnrolled, useEnrollGuest) and default export.
Redux: guestEnrollment removed
src/redux/slices/guestEnrollment.ts, src/redux/store.ts, src/redux/types/SliceName.ts
Removed guestEnrollment slice, selector, reducer wiring, persist whitelist entry, and the GUEST_ENROLLMENT enum member.
API & types
src/utils/auth/api.ts, types/auth/EnrollmentMethod.ts
Added EnrollmentMethod enum (MANUAL, AUTOMATIC); changed enrollUser to accept { courseId, enrollmentMethod } and include it in the POST payload.
Components: Start / Continue & StatusHeader
src/components/Course/Buttons/StartOrContinueLearning/index.tsx, src/components/Course/CourseDetails/StatusHeader/index.tsx
Simplified Start/Continue component to always use continue flow; StatusHeader now uses useEnrollUser with EnrollmentMethod.Manual, unified start handler (onStartHereClicked), guest redirect logic updated, CTA label set to "start-here".
Syllabus tab & styles
src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx, .../Syllabus.module.scss
Removed non-enrolled handling and toast logic; always render lesson title as a Link; removed .notEnrolledLink CSS class.
Lesson rendering
src/components/Course/LessonContent/index.tsx
Removed runtime enrollment check and NotEnrolledNotice short-circuit; lessons now render NextSeoWrapper / LessonView directly.
NotEnrolledNotice removed & styles
src/components/Course/NotEnrolledNotice/index.tsx, .../NotEnrolledNotice.module.scss
Deleted the NotEnrolledNotice component and removed .container { min-block-size: 70vh; } rule.
Page: learning-plan lesson
src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
Added DataFetcher onFetchSuccess to auto-enroll via useEnrollUser (AUTOMATIC); replaced NotEnrolledNotice/error render paths with login navigation and updated cache mutation.
Tests: guest access
tests/integration/learning-plans/guest-access.spec.ts
Reworked tests to use Start Here helpers (clickStartHereButton, clickStartHereAndReturnToCoursePage), renamed scrolling helper, added syllabus helper, and restructured test suites to reflect new flow.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Browser as "Client (Lesson Page)"
    participant Hook as "useEnrollUser"
    participant Auth as "AuthService"
    participant API as "enrollUser API"

    User->>Browser: Open lesson URL
    Browser->>Browser: DataFetcher fetches lesson
    Browser->>Hook: onFetchSuccess -> enroll(courseId, AUTOMATIC)
    activate Hook
    Hook->>Auth: isLoggedIn()
    alt logged in
        Auth-->>Hook: true
        Hook->>API: POST /enroll { courseId, enrollmentMethod: AUTOMATIC }
        API-->>Hook: { success: true }
        Hook-->>Browser: success
    else not logged in
        Auth-->>Hook: false
        Hook-->>Browser: { success: false }
        Browser->>User: redirect to login (or navigate to first lesson if guest access allowed)
    end
    deactivate Hook
    Browser->>User: Render lesson content (NextSeoWrapper / LessonView)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Files/areas to inspect closely:
    • src/components/Course/CourseDetails/StatusHeader/index.tsx (enroll flow, guest redirect, and navigation to first lesson).
    • src/hooks/auth/useEnrollUser.ts (isLoggedIn check, Sentry metadata, error paths, memoization).
    • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx (onFetchSuccess auto-enroll, cache mutation, and avoiding duplicate enroll calls).
    • Search for remaining usages/imports of removed guest enrollment slice and hooks.

Possibly related PRs

Suggested reviewers

  • AhmedCodeGuy
  • osamasayed

Poem

🐇 Hop-Hop! I nudged the guest path free,
Two new enums, one hook, and away we flee.
Start-here signs gleam, old Redux burrow cleared,
Lessons open wide — the path is steered.
🥕✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'QF-3518 open learning plans for guest users' clearly summarizes the main objective of enabling guest access to learning plans, which aligns with the primary changes in the changeset.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering all major sections: a clear summary with issue reference, type of change checkbox selection, detailed changes organized by component, test plan with manual testing steps, completed pre-review checklist, and important dependency/breaking change notes.
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 QF-3518-open-learning-plans

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.

Copy link
Contributor

@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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e6c9de4 and 809ba0d.

📒 Files selected for processing (16)
  • locales/en/learn.json (1 hunks)
  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx (2 hunks)
  • src/components/Course/CourseDetails/StatusHeader/index.tsx (5 hunks)
  • src/components/Course/CourseDetails/Tabs/Syllabus/Syllabus.module.scss (0 hunks)
  • src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx (2 hunks)
  • src/components/Course/LessonContent/index.tsx (2 hunks)
  • src/components/Course/NotEnrolledNotice/NotEnrolledNotice.module.scss (0 hunks)
  • src/components/Course/NotEnrolledNotice/index.tsx (0 hunks)
  • src/hooks/auth/useEnrollUser.ts (1 hunks)
  • src/hooks/auth/useGuestEnrollment.ts (0 hunks)
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx (0 hunks)
  • src/redux/slices/guestEnrollment.ts (0 hunks)
  • src/redux/store.ts (0 hunks)
  • src/redux/types/SliceName.ts (0 hunks)
  • src/utils/auth/api.ts (2 hunks)
  • types/auth/EnrollmentMethod.ts (1 hunks)
💤 Files with no reviewable changes (8)
  • src/components/Course/CourseDetails/Tabs/Syllabus/Syllabus.module.scss
  • src/components/Course/NotEnrolledNotice/index.tsx
  • src/redux/slices/guestEnrollment.ts
  • src/redux/store.ts
  • src/redux/types/SliceName.ts
  • src/components/Course/NotEnrolledNotice/NotEnrolledNotice.module.scss
  • src/hooks/auth/useGuestEnrollment.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
🧰 Additional context used
📓 Path-based instructions (14)
**/*.*

📄 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:

  • locales/en/learn.json
  • types/auth/EnrollmentMethod.ts
  • src/components/Course/LessonContent/index.tsx
  • src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx
  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx
  • src/hooks/auth/useEnrollUser.ts
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
  • src/utils/auth/api.ts
locales/**

📄 CodeRabbit inference engine (CLAUDE.md)

Keep translation files under locales/[lang]/ using next-translate conventions

Files:

  • locales/en/learn.json
**/*.{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:

  • types/auth/EnrollmentMethod.ts
  • src/components/Course/LessonContent/index.tsx
  • src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx
  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx
  • src/hooks/auth/useEnrollUser.ts
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
  • src/utils/auth/api.ts
**/*.{ts,tsx}

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

Use xstate for complex state logic

Files:

  • types/auth/EnrollmentMethod.ts
  • src/components/Course/LessonContent/index.tsx
  • src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx
  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx
  • src/hooks/auth/useEnrollUser.ts
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
  • src/utils/auth/api.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:

  • types/auth/EnrollmentMethod.ts
  • src/components/Course/LessonContent/index.tsx
  • src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx
  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx
  • src/hooks/auth/useEnrollUser.ts
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
  • src/utils/auth/api.ts
**/types/**/*.{ts,d.ts}

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

**/types/**/*.{ts,d.ts}: Export types and interfaces from dedicated type files when shared
Place shared types in a types directory

Files:

  • types/auth/EnrollmentMethod.ts
{src,types}/**/*.ts?(x)

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript throughout the codebase with strict configuration

Files:

  • types/auth/EnrollmentMethod.ts
  • src/components/Course/LessonContent/index.tsx
  • src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx
  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx
  • src/hooks/auth/useEnrollUser.ts
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
  • src/utils/auth/api.ts
{src,types}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • types/auth/EnrollmentMethod.ts
  • src/components/Course/LessonContent/index.tsx
  • src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx
  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx
  • src/hooks/auth/useEnrollUser.ts
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
  • src/utils/auth/api.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/Course/LessonContent/index.tsx
  • src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx
  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/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/Course/LessonContent/index.tsx
  • src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx
  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/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/Course/LessonContent/index.tsx
  • src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx
  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
src/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer React functional components for UI implementation

Files:

  • src/components/Course/LessonContent/index.tsx
  • src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx
  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
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/Course/LessonContent/index.tsx
  • src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx
  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/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 (17)
📓 Common learnings
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:26-27
Timestamp: 2025-10-22T20:51:18.747Z
Learning: Analytics naming convention in quran.com-frontend-next: For syllabus day clicks, retain the legacy event name 'course_syllabus_day' for logged-in users to preserve existing dashboards; only guest flows introduce the 'guest_' prefix (e.g., 'guest_course_syllabus_day'). Apply concise inline "why" comments near such analytics decisions to prevent accidental renaming.
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx:35-59
Timestamp: 2025-10-22T20:42:09.214Z
Learning: Preference for quran.com-frontend-next: keep single-use, page-specific components inline. Example: NotEnrolledMessage in src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx should remain inline; extract only if reused elsewhere.
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:44-49
Timestamp: 2025-10-22T20:33:55.176Z
Learning: Preference: In quran.com-frontend-next, keep concise “why” comments for analytics/UX decision points (e.g., guest vs enrolled click handlers) but avoid verbose JSDoc that repeats params/types. Convert multi-line JSDoc to brief inline rationale comments, especially in src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx and similar analytics handlers.
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: tests/integration/learning-plans/guest-access.spec.ts:3-5
Timestamp: 2025-10-22T20:39:29.339Z
Learning: Repository: quran/quran.com-frontend-next
Context: tests/integration/learning-plans/guest-access.spec.ts and similar focused integration tests
Learning: For focused integration tests that validate specific route behavior, maintainers prefer hard-coded route paths (e.g., LP_URL, FIRST_LESSON_URL) over environment-based URLs to avoid unnecessary complexity.
📚 Learning: 2025-10-22T20:42:09.214Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx:35-59
Timestamp: 2025-10-22T20:42:09.214Z
Learning: Preference for quran.com-frontend-next: keep single-use, page-specific components inline. Example: NotEnrolledMessage in src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx should remain inline; extract only if reused elsewhere.

Applied to files:

  • src/components/Course/LessonContent/index.tsx
  • src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx
  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
📚 Learning: 2025-10-22T20:33:55.176Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:44-49
Timestamp: 2025-10-22T20:33:55.176Z
Learning: Preference: In quran.com-frontend-next, keep concise “why” comments for analytics/UX decision points (e.g., guest vs enrolled click handlers) but avoid verbose JSDoc that repeats params/types. Convert multi-line JSDoc to brief inline rationale comments, especially in src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx and similar analytics handlers.

Applied to files:

  • src/components/Course/LessonContent/index.tsx
  • src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx
  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
📚 Learning: 2025-08-01T08:50:22.602Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react-functional-components.mdc:0-0
Timestamp: 2025-08-01T08:50:22.602Z
Learning: Applies to src/components/**/*.tsx : Always use React functional components with hooks.

Applied to files:

  • src/components/Course/LessonContent/index.tsx
  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Use custom hooks for reusable logic

Applied to files:

  • src/components/Course/LessonContent/index.tsx
  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/use*.{tsx,jsx} : Keep hooks focused and simple

Applied to files:

  • src/components/Course/LessonContent/index.tsx
  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Extract reusable logic into custom hooks

Applied to files:

  • src/components/Course/LessonContent/index.tsx
  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Use appropriate dependency arrays in useEffect

Applied to files:

  • src/components/Course/LessonContent/index.tsx
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Use useState for local component state

Applied to files:

  • src/components/Course/LessonContent/index.tsx
📚 Learning: 2025-08-01T08:49:45.154Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/next-js-app-router-rule.mdc:0-0
Timestamp: 2025-08-01T08:49:45.154Z
Learning: Applies to app/**/*.tsx : Follow Next.js documentation for best practices in data fetching, rendering, and routing

Applied to files:

  • src/components/Course/LessonContent/index.tsx
📚 Learning: 2025-10-07T08:37:58.213Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-07T08:37:58.213Z
Learning: Applies to src/**/*.tsx : Prefer React functional components for UI implementation

Applied to files:

  • src/components/Course/LessonContent/index.tsx
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Use functional components over class components

Applied to files:

  • src/components/Course/LessonContent/index.tsx
📚 Learning: 2025-10-22T20:51:18.747Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:26-27
Timestamp: 2025-10-22T20:51:18.747Z
Learning: Analytics naming convention in quran.com-frontend-next: For syllabus day clicks, retain the legacy event name 'course_syllabus_day' for logged-in users to preserve existing dashboards; only guest flows introduce the 'guest_' prefix (e.g., 'guest_course_syllabus_day'). Apply concise inline "why" comments near such analytics decisions to prevent accidental renaming.

Applied to files:

  • src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx
  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
📚 Learning: 2025-10-22T20:39:29.339Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: tests/integration/learning-plans/guest-access.spec.ts:3-5
Timestamp: 2025-10-22T20:39:29.339Z
Learning: Repository: quran/quran.com-frontend-next
Context: tests/integration/learning-plans/guest-access.spec.ts and similar focused integration tests
Learning: For focused integration tests that validate specific route behavior, maintainers prefer hard-coded route paths (e.g., LP_URL, FIRST_LESSON_URL) over environment-based URLs to avoid unnecessary complexity.

Applied to files:

  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx
📚 Learning: 2025-10-26T03:27:28.728Z
Learnt from: afifvdin
Repo: quran/quran.com-frontend-next PR: 2545
File: src/pages/reading-goal/index.tsx:31-35
Timestamp: 2025-10-26T03:27:28.728Z
Learning: In src/pages/reading-goal/index.tsx, the initialExampleKey is intentionally computed only when isLoggedIn() is true. This is by design: guest users can interact with the page and select options manually, but the example URL parameter only pre-selects an option for logged-in users (typically after being redirected back from login). The example selection is preserved through the authentication redirect flow.

Applied to files:

  • src/components/Course/Buttons/StartOrContinueLearning/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
📚 Learning: 2025-08-01T08:51:05.924Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/redux-toolkit-best-practices.mdc:0-0
Timestamp: 2025-08-01T08:51:05.924Z
Learning: Applies to src/redux/**/*.ts : Use Redux hooks (useSelector, useDispatch) in components.

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-10-07T08:37:58.213Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-07T08:37:58.213Z
Learning: Applies to src/utils/auth/api.ts : Place authentication API utilities in src/utils/auth/api.ts

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
  • src/utils/auth/api.ts
🔇 Additional comments (3)
locales/en/learn.json (1)

41-41: New start-here copy and key look consistent

Key naming and casing match existing learn namespace entries; no issues from i18n or UX perspective.

src/components/Course/Buttons/StartOrContinueLearning/index.tsx (1)

23-25: Guard against missing redirect lesson slug

The simplified redirect logic is clear, but if a course ever has neither continueFromLesson nor any lessons, redirectToLessonSlug becomes undefined, and getLessonNavigationUrl(slug, redirectToLessonSlug) will build an invalid route.

TODO: Either assert the invariant or guard the edge case. For example:

- const redirectToLessonSlug = continueFromLesson || lessons?.[0]?.slug;
+ const redirectToLessonSlug = continueFromLesson || lessons?.[0]?.slug;
+
+ if (!redirectToLessonSlug) {
+   // TODO: No lesson to continue from; consider disabling the button or rendering nothing.
+   return null;
+ }

If the domain model guarantees at least one lesson for any course that renders this component, just document that assumption in a brief comment.

Also applies to: 26-33, 35-35

src/components/Course/CourseDetails/StatusHeader/index.tsx (1)

14-19: Unified “Start here” flow looks correct; tidy up EnrollmentMethod import and error handling details

The overall flow matches the new design well: guests are either taken straight to the first lesson (when allowGuestAccess) or to login, and logged‑in users enroll with EnrollmentMethod.Manual, update cached course state, and then navigate to the first lesson. CTA vs non‑CTA behavior is also clear.

A few refinements:

  1. Avoid potential double Sentry logging

    useEnrollUser already logs errors to Sentry before rethrowing. The catch block here logs again:

    } catch (error) {
      logErrorToSentry(error, {
        metadata: {
          context: `${userType}_course_enrollment`,
          courseId: id,
          courseSlug: slug,
        },
      });
      toast(t('common:error.general'), { status: ToastStatus.Error });
    }

    TODO: Decide where you want the single source of error logging. Options:

    • Remove logging from useEnrollUser and keep this richer context here, or
    • Keep logging in useEnrollUser and drop the extra logErrorToSentry here, retaining just the toast.
  2. Defensive mutate callback (optional)

    If useMutateWithoutRevalidation can ever invoke the updater with undefined (e.g., cache not primed), spreading currentCourse would throw. To be safe:

  •  mutate(makeGetCourseUrl(slug), (currentCourse: Course) => ({
    
  •    ...currentCourse,
    
  •    isUserEnrolled: true,
    
  •  }));
    
  •  mutate(makeGetCourseUrl(slug), (currentCourse?: Course) =>
    
  •    currentCourse
    
  •      ? { ...currentCourse, isUserEnrolled: true }
    
  •      : currentCourse,
    
  •  );
    
    
    If the cache is guaranteed to be populated here, this is purely defensive.
    
    
  1. Align EnrollmentMethod import path

    As with the other files, standardize on the canonical EnrollmentMethod module path:

  • import EnrollmentMethod from '@/types/auth/EnrollmentMethod';
  • import EnrollmentMethod from 'types/auth/EnrollmentMethod';
    
    

TODO: Address the logging duplication and import path consistency; consider the mutate guard if there’s any chance the cache entry is missing.

Also applies to: 34-42, 43-89, 91-101, 103-125

…o return success status, simplifying error handling, and removing unnecessary code from StatusHeader and LessonContent components. Implement automatic enrollment in LessonPage upon successful data fetch.
Copy link
Contributor

@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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/Course/CourseDetails/StatusHeader/index.tsx (1)

42-81: Harden onStartHereClicked loading state and navigation flow

The enrollment flow looks correct, but setIsLoading(false) only runs if nothing between enrollUserInCourse, mutate, and router.push throws. Also, awaiting router.push isn’t necessary here and can cause a state update after unmount.

You can make this more robust:

   const onStartHereClicked = async (): Promise<void> => {
@@
-    // Logged-in user - enroll with MANUAL method
-    setIsLoading(true);
-    const { success } = await enrollUserInCourse(id, EnrollmentMethod.Manual);
-
-    if (success) {
-      mutate(makeGetCourseUrl(slug), (currentCourse: Course) => ({
-        ...currentCourse,
-        isUserEnrolled: true,
-      }));
-
-      if (lessons?.length > 0) {
-        await router.push(getLessonNavigationUrl(slug, lessons[0].slug));
-      }
-    } else {
-      toast(t('common:error.general'), {
-        status: ToastStatus.Error,
-      });
-    }
-
-    setIsLoading(false);
+    // Logged-in user - enroll with MANUAL method
+    setIsLoading(true);
+    try {
+      const { success } = await enrollUserInCourse(id, EnrollmentMethod.Manual);
+
+      if (!success) {
+        toast(t('common:error.general'), {
+          status: ToastStatus.Error,
+        });
+        return;
+      }
+
+      mutate(makeGetCourseUrl(slug), (currentCourse: Course) => ({
+        ...currentCourse,
+        isUserEnrolled: true,
+      }));
+
+      if (lessons?.length > 0) {
+        void router.push(getLessonNavigationUrl(slug, lessons[0].slug));
+      }
+    } finally {
+      setIsLoading(false);
+    }
   };

This keeps the UX the same while ensuring loading state is always reset and avoiding unnecessary coupling to the navigation promise.

Also applies to: 83-88, 112-116

♻️ Duplicate comments (1)
src/hooks/auth/useEnrollUser.ts (1)

36-41: Align Sentry transactionName with shared “enroll_user” convention

Previous feedback suggested using a shared transaction name for enrollment operations. To keep Sentry traces coherent with other enrollment paths, consider switching to the agreed name:

-        logErrorToSentry(error, {
-          transactionName: 'useEnrollUser',
+        logErrorToSentry(error, {
+          transactionName: 'enroll_user',
           metadata: { courseId, enrollmentMethod },
         });

This makes it easier to aggregate all enrollment failures under a single transaction in Sentry.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 809ba0d and a03191f.

📒 Files selected for processing (4)
  • src/components/Course/CourseDetails/StatusHeader/index.tsx (4 hunks)
  • src/components/Course/LessonContent/index.tsx (0 hunks)
  • src/hooks/auth/useEnrollUser.ts (1 hunks)
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx (3 hunks)
💤 Files with no reviewable changes (1)
  • src/components/Course/LessonContent/index.tsx
🧰 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/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/hooks/auth/useEnrollUser.ts
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
**/*.{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/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/hooks/auth/useEnrollUser.ts
  • src/components/Course/CourseDetails/StatusHeader/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/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/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/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
**/*.{ts,tsx}

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

Use xstate for complex state logic

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/hooks/auth/useEnrollUser.ts
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
**/*.{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/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/hooks/auth/useEnrollUser.ts
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
src/pages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Next.js Pages Router; place all route files under src/pages

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
{src,types}/**/*.ts?(x)

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript throughout the codebase with strict configuration

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/hooks/auth/useEnrollUser.ts
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
src/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer React functional components for UI implementation

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
{src,types}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/hooks/auth/useEnrollUser.ts
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
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/Course/CourseDetails/StatusHeader/index.tsx
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/Course/CourseDetails/StatusHeader/index.tsx
🧠 Learnings (17)
📓 Common learnings
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:26-27
Timestamp: 2025-10-22T20:51:18.747Z
Learning: Analytics naming convention in quran.com-frontend-next: For syllabus day clicks, retain the legacy event name 'course_syllabus_day' for logged-in users to preserve existing dashboards; only guest flows introduce the 'guest_' prefix (e.g., 'guest_course_syllabus_day'). Apply concise inline "why" comments near such analytics decisions to prevent accidental renaming.
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx:35-59
Timestamp: 2025-10-22T20:42:09.214Z
Learning: Preference for quran.com-frontend-next: keep single-use, page-specific components inline. Example: NotEnrolledMessage in src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx should remain inline; extract only if reused elsewhere.
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:44-49
Timestamp: 2025-10-22T20:33:55.176Z
Learning: Preference: In quran.com-frontend-next, keep concise “why” comments for analytics/UX decision points (e.g., guest vs enrolled click handlers) but avoid verbose JSDoc that repeats params/types. Convert multi-line JSDoc to brief inline rationale comments, especially in src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx and similar analytics handlers.
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: tests/integration/learning-plans/guest-access.spec.ts:3-5
Timestamp: 2025-10-22T20:39:29.339Z
Learning: Repository: quran/quran.com-frontend-next
Context: tests/integration/learning-plans/guest-access.spec.ts and similar focused integration tests
Learning: For focused integration tests that validate specific route behavior, maintainers prefer hard-coded route paths (e.g., LP_URL, FIRST_LESSON_URL) over environment-based URLs to avoid unnecessary complexity.
📚 Learning: 2025-10-22T20:42:09.214Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx:35-59
Timestamp: 2025-10-22T20:42:09.214Z
Learning: Preference for quran.com-frontend-next: keep single-use, page-specific components inline. Example: NotEnrolledMessage in src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx should remain inline; extract only if reused elsewhere.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
📚 Learning: 2025-10-22T20:33:55.176Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:44-49
Timestamp: 2025-10-22T20:33:55.176Z
Learning: Preference: In quran.com-frontend-next, keep concise “why” comments for analytics/UX decision points (e.g., guest vs enrolled click handlers) but avoid verbose JSDoc that repeats params/types. Convert multi-line JSDoc to brief inline rationale comments, especially in src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx and similar analytics handlers.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/hooks/auth/useEnrollUser.ts
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
📚 Learning: 2025-10-22T20:51:18.747Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:26-27
Timestamp: 2025-10-22T20:51:18.747Z
Learning: Analytics naming convention in quran.com-frontend-next: For syllabus day clicks, retain the legacy event name 'course_syllabus_day' for logged-in users to preserve existing dashboards; only guest flows introduce the 'guest_' prefix (e.g., 'guest_course_syllabus_day'). Apply concise inline "why" comments near such analytics decisions to prevent accidental renaming.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
📚 Learning: 2025-08-01T08:49:45.154Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/next-js-app-router-rule.mdc:0-0
Timestamp: 2025-08-01T08:49:45.154Z
Learning: Applies to app/**/*.tsx : Follow Next.js documentation for best practices in data fetching, rendering, and routing

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-08-01T08:50:03.171Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/next-js-conventions.mdc:0-0
Timestamp: 2025-08-01T08:50:03.171Z
Learning: Refer to Next.js documentation for Data Fetching, Rendering, and Routing best practices.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/use*.{tsx,jsx} : Keep hooks focused and simple

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-08-01T08:50:03.171Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/next-js-conventions.mdc:0-0
Timestamp: 2025-08-01T08:50:03.171Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Rely on Next.js Pages Router for state changes.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-10-07T08:37:58.213Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-07T08:37:58.213Z
Learning: Applies to src/pages/**/*.{ts,tsx} : Use Next.js Pages Router; place all route files under src/pages

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-09-21T18:32:41.811Z
Learnt from: mohsinayoob
Repo: quran/quran.com-frontend-next PR: 2495
File: src/pages/logout.tsx:12-17
Timestamp: 2025-09-21T18:32:41.811Z
Learning: In the Next.js codebase, redirect-only pages like src/pages/logout.tsx intentionally use GetServerSidePropsResult<any> in JSDoc comments because they only perform server-side redirects without passing meaningful data to client-side rendering.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Use custom hooks for reusable logic

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Extract reusable logic into custom hooks

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-08-01T08:51:05.924Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/redux-toolkit-best-practices.mdc:0-0
Timestamp: 2025-08-01T08:51:05.924Z
Learning: Applies to src/redux/**/*.ts : Use Redux hooks (useSelector, useDispatch) in components.

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-08-01T08:50:22.602Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react-functional-components.mdc:0-0
Timestamp: 2025-08-01T08:50:22.602Z
Learning: Applies to src/components/**/*.tsx : Always use React functional components with hooks.

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-10-07T08:37:58.213Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-07T08:37:58.213Z
Learning: Applies to src/utils/auth/api.ts : Place authentication API utilities in src/utils/auth/api.ts

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Implement proper memoization (useMemo, useCallback)

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-10-26T03:27:28.728Z
Learnt from: afifvdin
Repo: quran/quran.com-frontend-next PR: 2545
File: src/pages/reading-goal/index.tsx:31-35
Timestamp: 2025-10-26T03:27:28.728Z
Learning: In src/pages/reading-goal/index.tsx, the initialExampleKey is intentionally computed only when isLoggedIn() is true. This is by design: guest users can interact with the page and select options manually, but the example URL parameter only pre-selects an option for logged-in users (typically after being redirected back from login). The example selection is preserved through the authentication redirect flow.

Applied to files:

  • src/components/Course/CourseDetails/StatusHeader/index.tsx
🧬 Code graph analysis (3)
src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx (1)
types/auth/Course.ts (1)
  • Lesson (3-16)
src/hooks/auth/useEnrollUser.ts (3)
src/utils/auth/login.ts (1)
  • isLoggedIn (17-17)
src/utils/auth/api.ts (1)
  • enrollUser (457-464)
src/lib/sentry.ts (1)
  • logErrorToSentry (123-152)
src/components/Course/CourseDetails/StatusHeader/index.tsx (5)
src/components/dls/Toast/Toast.tsx (1)
  • useToast (86-96)
src/utils/auth/login.ts (1)
  • isLoggedIn (17-17)
src/utils/navigation.ts (3)
  • getLessonNavigationUrl (355-356)
  • getLoginNavigationUrl (405-406)
  • getCourseNavigationUrl (346-347)
src/utils/auth/apiPaths.ts (1)
  • makeGetCourseUrl (145-145)
types/auth/Course.ts (1)
  • Course (29-48)

…llUser function, enhancing clarity and simplifying the enrollment process.
Copy link
Contributor

@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: 1

♻️ Duplicate comments (1)
src/hooks/auth/useEnrollUser.ts (1)

43-43: Add dependencies to satisfy exhaustive-deps rule.

Previous review feedback requested adding [enrollUser, isLoggedIn, logErrorToSentry] to the dependency array. While these imported functions are stable in practice, including them satisfies the react-hooks/exhaustive-deps linting rule and follows React best practices.

Apply this diff:

     },
-    [],
+    [enrollUser, isLoggedIn, logErrorToSentry],
   );

As per coding guidelines and learnings: "Use appropriate dependency arrays in useEffect" and similar hooks.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a03191f and 4de3b31.

📒 Files selected for processing (1)
  • src/hooks/auth/useEnrollUser.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.*

📄 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/hooks/auth/useEnrollUser.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/hooks/auth/useEnrollUser.ts
**/*.{ts,tsx}

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

Use xstate for complex state logic

Files:

  • src/hooks/auth/useEnrollUser.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/hooks/auth/useEnrollUser.ts
{src,types}/**/*.ts?(x)

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript throughout the codebase with strict configuration

Files:

  • src/hooks/auth/useEnrollUser.ts
{src,types}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • src/hooks/auth/useEnrollUser.ts
🧠 Learnings (10)
📓 Common learnings
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx:35-59
Timestamp: 2025-10-22T20:42:09.214Z
Learning: Preference for quran.com-frontend-next: keep single-use, page-specific components inline. Example: NotEnrolledMessage in src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx should remain inline; extract only if reused elsewhere.
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:26-27
Timestamp: 2025-10-22T20:51:18.747Z
Learning: Analytics naming convention in quran.com-frontend-next: For syllabus day clicks, retain the legacy event name 'course_syllabus_day' for logged-in users to preserve existing dashboards; only guest flows introduce the 'guest_' prefix (e.g., 'guest_course_syllabus_day'). Apply concise inline "why" comments near such analytics decisions to prevent accidental renaming.
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: tests/integration/learning-plans/guest-access.spec.ts:3-5
Timestamp: 2025-10-22T20:39:29.339Z
Learning: Repository: quran/quran.com-frontend-next
Context: tests/integration/learning-plans/guest-access.spec.ts and similar focused integration tests
Learning: For focused integration tests that validate specific route behavior, maintainers prefer hard-coded route paths (e.g., LP_URL, FIRST_LESSON_URL) over environment-based URLs to avoid unnecessary complexity.
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:44-49
Timestamp: 2025-10-22T20:33:55.176Z
Learning: Preference: In quran.com-frontend-next, keep concise “why” comments for analytics/UX decision points (e.g., guest vs enrolled click handlers) but avoid verbose JSDoc that repeats params/types. Convert multi-line JSDoc to brief inline rationale comments, especially in src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx and similar analytics handlers.
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/use*.{tsx,jsx} : Keep hooks focused and simple

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-08-01T08:51:05.924Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/redux-toolkit-best-practices.mdc:0-0
Timestamp: 2025-08-01T08:51:05.924Z
Learning: Applies to src/redux/**/*.ts : Use Redux hooks (useSelector, useDispatch) in components.

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Extract reusable logic into custom hooks

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Use custom hooks for reusable logic

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-08-01T08:50:22.602Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react-functional-components.mdc:0-0
Timestamp: 2025-08-01T08:50:22.602Z
Learning: Applies to src/components/**/*.tsx : Always use React functional components with hooks.

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-10-07T08:37:58.213Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-07T08:37:58.213Z
Learning: Applies to src/utils/auth/api.ts : Place authentication API utilities in src/utils/auth/api.ts

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Implement proper memoization (useMemo, useCallback)

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-10-22T20:33:55.176Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:44-49
Timestamp: 2025-10-22T20:33:55.176Z
Learning: Preference: In quran.com-frontend-next, keep concise “why” comments for analytics/UX decision points (e.g., guest vs enrolled click handlers) but avoid verbose JSDoc that repeats params/types. Convert multi-line JSDoc to brief inline rationale comments, especially in src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx and similar analytics handlers.

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Use appropriate dependency arrays in useEffect

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
🧬 Code graph analysis (1)
src/hooks/auth/useEnrollUser.ts (3)
src/utils/auth/login.ts (1)
  • isLoggedIn (17-17)
src/utils/auth/api.ts (1)
  • enrollUser (457-464)
src/lib/sentry.ts (1)
  • logErrorToSentry (123-152)
⏰ 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: test
🔇 Additional comments (5)
src/hooks/auth/useEnrollUser.ts (5)

8-18: Excellent documentation of error handling contract.

The JSDoc clearly communicates that this hook doesn't throw (safe for fire-and-forget usage in automatic enrollment flows) and returns a result object instead. This addresses previous concerns and helps prevent unhandled promise rejections.


19-27: Good use of early return pattern.

The early return for non-logged-in users prevents unnecessary API calls and improves readability, following coding guidelines effectively.


29-34: Success propagation correctly implemented.

The hook now properly destructures and returns the success flag from the backend response. This addresses previous feedback and allows callers to distinguish between backend success and failure cases.


36-38: Clarify transactionName feedback from previous review.

A previous reviewer (osamasayed) commented: "transactionName: 'enroll_user', 1 level higher". The current implementation uses 'useEnrollUser' as the transaction name. Please clarify:

  1. Should the transaction name be 'enroll_user' instead of 'useEnrollUser'?
  2. What does "1 level higher" mean in this context?

Based on learnings, analytics naming conventions matter for dashboard consistency. If 'enroll_user' is the established convention for enrollment events, the transaction name should match.


4-4: Import path is correct.

The file properly uses @/types/auth/EnrollmentMethod, which aligns with the coding guidelines ("Use path aliases @/ for src imports") and the modern convention across the codebase. While older code in src/api.ts and some src/components/ files use bare types/ paths, newer utilities and hooks consistently use the @/ prefix. The original review comment suggesting a bare path was based on an outdated pattern.

@osamasayed osamasayed requested a review from Copilot November 25, 2025 07:56
Copilot finished reviewing on behalf of osamasayed November 25, 2025 08:00
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 removes guest enrollment functionality and implements enrollment method tracking to align with backend API changes. The changes enable automatic enrollment for logged-in users when they view lessons and track whether enrollment was manual (via "Start here" button) or automatic (when accessing lessons directly).

Key Changes:

  • Removed guest enrollment infrastructure (Redux slice, hooks, and related components)
  • Added EnrollmentMethod enum to track manual vs automatic enrollment
  • Implemented automatic enrollment when logged-in users access lesson pages
  • Updated enrollment API to accept enrollmentMethod parameter

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
types/auth/EnrollmentMethod.ts New enum defining MANUAL and AUTOMATIC enrollment methods
src/utils/auth/api.ts Updated enrollUser function to accept enrollment method parameter
src/redux/types/SliceName.ts Removed GUEST_ENROLLMENT enum value
src/redux/store.ts Removed guest enrollment from Redux store and persist config
src/redux/slices/guestEnrollment.ts Deleted guest enrollment Redux slice
src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx Added automatic enrollment logic via onFetchSuccess callback
src/hooks/auth/useGuestEnrollment.ts Deleted guest enrollment hooks
src/hooks/auth/useEnrollUser.ts New hook for enrolling logged-in users with error handling
src/components/Course/NotEnrolledNotice/index.tsx Deleted component no longer needed without guest enrollment checks
src/components/Course/NotEnrolledNotice/NotEnrolledNotice.module.scss Deleted associated styles
src/components/Course/LessonContent/index.tsx Removed enrollment checks and NotEnrolledNotice component usage
src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx Removed enrollment checks - all lessons now clickable
src/components/Course/CourseDetails/Tabs/Syllabus/Syllabus.module.scss Removed .notEnrolledLink styles
src/components/Course/CourseDetails/StatusHeader/index.tsx Updated to use useEnrollUser hook with manual enrollment method, renamed "Enroll" to "Start here"
src/components/Course/Buttons/StartOrContinueLearning/index.tsx Simplified to always show "Continue Learning" button
locales/en/learn.json Added "start-here" translation key

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

Comment on lines 26 to 33
const handleFetchSuccess: (data: any) => void = useCallback(
(lesson: Lesson) => {
if (lesson?.course && !lesson.course.isUserEnrolled) {
enrollUserInCourse(lesson.course.id, EnrollmentMethod.Automatic);
}
},
[enrollUserInCourse],
);
Copy link

Copilot AI Nov 25, 2025

Choose a reason for hiding this comment

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

The automatic enrollment may trigger on every revalidation of the lesson data. Since onFetchSuccess is called in the DataFetcher's promise chain (line 48 of DataFetcher), it will execute every time SWR revalidates the data, not just on the initial fetch. This could result in redundant API calls to enroll the user even after they're already enrolled.

Consider adding a check to prevent re-enrollment or using a ref to track if enrollment has been attempted for this course.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The worry isn’t accurate.
We already gate on lesson.course.isUserEnrolled, so once the backend marks the user as enrolled, enrollUserInCourse stops running.
Plus DataFetcher uses useSWRImmutable, so it only fires on the initial fetch unless we manually revalidate.

…an reader from "Begin Now" to "Start Now" to enhance user engagement.
…finition by removing explicit type annotation, improving code readability.
@osamasayed osamasayed requested a review from Copilot November 30, 2025 17:14
Copilot finished reviewing on behalf of osamasayed November 30, 2025 17:22
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

Copilot reviewed 17 out of 17 changed files in this pull request and generated 8 comments.

"reflection-description-1": "Clicking \"Add Reflection\" will take you to QuranReflect, a platform for sharing personal reflections on the Quran. Unlike Tafsir (scholarly interpretation), reflections are personal insights and experiences related to the verses.",
"reflection-description-2": "If you post publicly, your reflection will be reviewed by the moderation team and become visible to the QuranReflect community.",
"start-here": "Start here",
"start-learning": "Start Learning",
Copy link

Copilot AI Nov 30, 2025

Choose a reason for hiding this comment

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

The translation key 'start-learning' is still defined in the locale file but is no longer used anywhere in the code after the simplification of the StartOrContinueLearning component. This is dead code that should be removed from locales/en/learn.json.

Suggested change
"start-learning": "Start Learning",

Copilot uses AI. Check for mistakes.
…uppercase naming convention for consistency. Update related function calls in CourseDetails and LessonPage components to match the new naming, enhancing code clarity.
…returning the success status from enrollUser, improving error handling and reducing code complexity. Update LessonPage to handle specific enrollment errors and navigate accordingly.
Copy link
Contributor

@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: 1

♻️ Duplicate comments (2)
src/hooks/auth/useEnrollUser.ts (2)

32-32: Fix the useCallback dependency array to satisfy React hooks rules.

The empty dependency array violates react-hooks/exhaustive-deps. While enrollUser, isLoggedIn, and logErrorToSentry are module-level imports that won't change between renders, including them prevents linter warnings and documents the hook's dependencies explicitly.

As per coding guidelines: "Use appropriate dependency arrays in useEffect hooks" and "Follow the Rules of Hooks in React."

Apply this diff:

-  }, []);
+  }, [enrollUser, isLoggedIn, logErrorToSentry]);

25-30: Use safer type narrowing for the caught error.

The caught error could be any type (string, number, object, etc.), not just an Error instance. Checking with instanceof Error prevents runtime issues when logging or accessing error properties.

As per coding guidelines: "Avoid type assertions unless necessary in TypeScript" and "Ensure error types are properly typed, not any."

Apply this diff:

     } catch (error) {
       logErrorToSentry(error, {
         transactionName: 'useEnrollUser',
         metadata: { courseId, enrollmentMethod },
       });
-      return { success: false };
+      return { 
+        success: false,
+        error: error instanceof Error ? error : new Error(String(error))
+      };
     }

Note: This assumes the return type should include an optional error property. If the current { success: boolean } contract is sufficient, you can keep the existing return but still pass a normalized error to Sentry.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d69165 and bbcacb3.

📒 Files selected for processing (2)
  • src/hooks/auth/useEnrollUser.ts (1 hunks)
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx (3 hunks)
🧰 Additional context used
📓 Path-based instructions (19)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript with strict configuration
Use path alias @/ for src/ and @/dls/* for design system components

**/*.{ts,tsx}: Flag usage of any type in TypeScript - prefer unknown or specific types
Require explicit return types for public/exported functions in TypeScript
Prefer interface over type for object definitions in TypeScript
Use type for unions, intersections, and mapped types in TypeScript
Require enums for repeated raw values of the same category in TypeScript

**/*.{ts,tsx}: Flag any usage of any type - suggest unknown or specific types instead
Require explicit return types for all exported/public functions
Flag implicit any in function parameters
Ensure strict null checks are handled properly
Prefer interface for object shape definitions
Use type only for unions, intersections, and mapped types
Flag type usage where interface is more appropriate
Require enums when the same raw values appear multiple times
Flag repeated string/number literals that should be enums
Use PascalCase for types, interfaces, enums, and components
Use camelCase for variables, functions, and methods
Use UPPER_SNAKE_CASE for constants
Prefix Props interfaces with component name: ButtonProps, ModalProps
Flag unhandled Promise rejections
Require try-catch blocks for async operations
Ensure error types are properly typed, not any
Flag unused imports
Ensure imports are alphabetized within groups
Group import order: React → External packages → Internal modules → Types

**/*.{ts,tsx}: Flag any any types - use unknown or specific types instead
Require explicit return types on exported functions
Use interfaces for object shapes, types for unions in TypeScript
Use enums for repeated categorical values in TypeScript
Functions should be under 30 lines
Flag duplicated code - extract to reusable functions (DRY principle)
Require proper error handling with meaningful fallbacks
Flag unused imports, variables, or dead code
Comments shou...

Files:

  • src/hooks/auth/useEnrollUser.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
src/hooks/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Place custom React hooks in src/hooks/

Use useSWR for data fetching with caching

Files:

  • src/hooks/auth/useEnrollUser.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use API utilities from src/utils/auth/api.ts for authenticated requests

Files:

  • src/hooks/auth/useEnrollUser.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
**/*.*

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

Add comments starting with 'TODO:' to outline problems or bugs encountered in existing code

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

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

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

**/*.*: Only modify sections of the code related to the task at hand
Avoid modifying unrelated pieces of code
Accomplish goals with minimal code changes

**/*.*: 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/hooks/auth/useEnrollUser.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
**/*.{js,ts,jsx,tsx,java,py,cs,cpp,c,go,rb,php}

📄 CodeRabbit inference engine (.cursor/rules/clean-code.mdc)

**/*.{js,ts,jsx,tsx,java,py,cs,cpp,c,go,rb,php}: Replace hard-coded values with named constants and use descriptive constant names that explain the value's purpose
Keep constants at the top of the file or in a dedicated constants file
Variables, functions, and classes should reveal their purpose with meaningful names that explain why something exists and how it's used
Avoid abbreviations in names unless they're universally understood
Use comments to explain why something is done a certain way, not what the code does - make the code self-documenting
Document APIs, complex algorithms, and non-obvious side effects in comments
Each function should do exactly one thing and be small and focused
If a function needs a comment to explain what it does, it should be split into smaller, more focused functions
Extract repeated code into reusable functions and share common logic through proper abstraction
Keep related code together and organize code in a logical hierarchy
Hide implementation details and expose clear interfaces through encapsulation
Move nested conditionals into well-named functions for better readability

Files:

  • src/hooks/auth/useEnrollUser.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
**/*.{ts,js,jsx,tsx}

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

**/*.{ts,js,jsx,tsx}: Rely on Next.js Pages Router for state changes
Prioritize Web Vitals (LCP, CLS, FID) in performance optimization
Minimize 'use client' usage - prefer server components and Next.js SSR features
Use 'use client' only for Web API access in small components
Avoid using 'use client' for data fetching or state management

Files:

  • src/hooks/auth/useEnrollUser.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/performance-optimization-rules.mdc)

Optimize Web Vitals (LCP, CLS, FID) in JavaScript and TypeScript files

Files:

  • src/hooks/auth/useEnrollUser.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
**/*.{ts,tsx,d.ts}

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

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

Files:

  • src/hooks/auth/useEnrollUser.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx,js,jsx}: Flag functions exceeding 30 lines - should be split
Identify duplicated code that should be extracted to reusable functions (DRY principle)
Flag unused imports, variables, or dead code
Require proper error handling with meaningful fallbacks
Flag skipped linting rules without clear justification
Ensure complex logic has inline comments explaining 'why'
Ensure environment variables are used for configuration instead of hardcoded values
Flag missing input validation or sanitization
Flag undocumented complex business logic

Files:

  • src/hooks/auth/useEnrollUser.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
**/*.{tsx,jsx,ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{tsx,jsx,ts,js}: Flag hardcoded strings that should be localized
Ensure proper authentication checks for protected routes

Files:

  • src/hooks/auth/useEnrollUser.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
**/*.{ts,tsx,js,jsx,json,env,yml,yaml}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Flag any hardcoded credentials or secrets

Files:

  • src/hooks/auth/useEnrollUser.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.github/instructions/security.instructions.md)

**/*.{ts,tsx,js}: Flag ANY hardcoded credentials, API keys, or secrets in TypeScript/JavaScript code
Ensure all sensitive values use environment variables instead of hardcoding
Use NEXT_PUBLIC_ prefix only for client-side variables in environment variable declarations
Flag sensitive data exposed to client-side code
Require validation for all user inputs in TypeScript/JavaScript code
Flag direct usage of user input without sanitization, particularly with dangerouslySetInnerHTML
Ensure proper encoding for dynamic content to prevent injection attacks
Flag protected routes without auth checks in Next.js applications
Ensure proper session validation for authenticated requests
Flag sensitive operations without authentication checks

Files:

  • src/hooks/auth/useEnrollUser.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
src/pages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

src/pages/**/*.{ts,tsx}: Use Next.js 14 with Pages Router (not App Router)
Protect routes using withAuth HOC

Use Next.js 14 with Pages Router (NOT App Router) as the framework

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/performance-optimization-rules.mdc)

Use dynamic loading for non-critical components using @src/components/dls/Spinner/Spinner.tsx

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
**/*.{tsx,jsx}

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

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

**/*.{tsx,jsx}: Require functional components only (...

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
src/**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/redux-toolkit-best-practices.mdc)

src/**/*.tsx: Use selectors for accessing state in components
Use Redux hooks (useSelector, useDispatch) in components

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
**/*.tsx

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

Prefix React component prop interfaces with 'Props' (e.g., ButtonProps) in TypeScript

**/*.tsx: Use functional components only - no class components in React
Props interface must be defined for React components
Use proper memoization (useCallback, useMemo) for callbacks and expensive computations in React components
Flag unnecessary useEffect - prefer event handlers or derived state in React components
Require skeleton loaders for async data to prevent layout shifts in React components
Use useSWR for data fetching, not raw fetch in React components
Use optimistic updates for predictable actions (bookmark, like) in React components
No hardcoded strings in UI
Use semantic HTML elements in React components
Add ARIA attributes where needed for accessibility in React components
Ensure keyboard navigation works in React components

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
**/*.{tsx,jsx,css,module.css}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Ensure RTL (right-to-left) support is maintained

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
{src/components,src/pages}/**/*.tsx

📄 CodeRabbit inference engine (.github/instructions/localization.instructions.md)

{src/components,src/pages}/**/*.tsx: Flag ALL hardcoded user-facing strings - must use next-translate hook for text content
Use descriptive, hierarchical key names for translation keys and group related translations under common prefixes
Ensure interpolation is used for dynamic values in translations instead of string concatenation
Flag string concatenation with translated text - use translation interpolation instead

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
🧠 Learnings (55)
📓 Common learnings
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx:35-59
Timestamp: 2025-10-22T20:42:09.214Z
Learning: Preference for quran.com-frontend-next: keep single-use, page-specific components inline. Example: NotEnrolledMessage in src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx should remain inline; extract only if reused elsewhere.
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:26-27
Timestamp: 2025-10-22T20:51:18.747Z
Learning: Analytics naming convention in quran.com-frontend-next: For syllabus day clicks, retain the legacy event name 'course_syllabus_day' for logged-in users to preserve existing dashboards; only guest flows introduce the 'guest_' prefix (e.g., 'guest_course_syllabus_day'). Apply concise inline "why" comments near such analytics decisions to prevent accidental renaming.
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: tests/integration/learning-plans/guest-access.spec.ts:3-5
Timestamp: 2025-10-22T20:39:29.339Z
Learning: Repository: quran/quran.com-frontend-next
Context: tests/integration/learning-plans/guest-access.spec.ts and similar focused integration tests
Learning: For focused integration tests that validate specific route behavior, maintainers prefer hard-coded route paths (e.g., LP_URL, FIRST_LESSON_URL) over environment-based URLs to avoid unnecessary complexity.
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:44-49
Timestamp: 2025-10-22T20:33:55.176Z
Learning: Preference: In quran.com-frontend-next, keep concise “why” comments for analytics/UX decision points (e.g., guest vs enrolled click handlers) but avoid verbose JSDoc that repeats params/types. Convert multi-line JSDoc to brief inline rationale comments, especially in src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx and similar analytics handlers.
📚 Learning: 2025-11-25T13:18:33.501Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T13:18:33.501Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Place custom React hooks in src/hooks/

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-25T13:20:48.459Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-11-25T13:20:48.459Z
Learning: Applies to **/*.{tsx,jsx} : Use custom hooks for reusable logic in React

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:31:06.687Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T12:31:06.687Z
Learning: Applies to src/hooks/**/*.{ts,tsx} : Use useSWR for data fetching with caching

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-25T13:20:48.459Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-11-25T13:20:48.459Z
Learning: Applies to **/*.{tsx,jsx} : Extract reusable logic into custom hooks in React

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-25T13:20:26.998Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react-functional-components.mdc:0-0
Timestamp: 2025-11-25T13:20:26.998Z
Learning: Applies to src/components/**/*.tsx : Always use React functional components with hooks in React components

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-28T12:29:33.962Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T12:29:33.962Z
Learning: Applies to **/*.{tsx,jsx} : Ensure proper memoization with `useMemo` and `useCallback` where appropriate in React

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:18:33.501Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T13:18:33.501Z
Learning: Applies to src/**/*.{ts,tsx} : Use API utilities from src/utils/auth/api.ts for authenticated requests

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-25T13:20:58.280Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/redux-toolkit-best-practices.mdc:0-0
Timestamp: 2025-11-25T13:20:58.280Z
Learning: Applies to src/**/*.tsx : Use Redux hooks (useSelector, useDispatch) in components

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-25T13:20:48.459Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-11-25T13:20:48.459Z
Learning: Applies to **/*.{tsx,jsx} : Keep React hooks focused and simple

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-10-22T20:33:55.176Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:44-49
Timestamp: 2025-10-22T20:33:55.176Z
Learning: Preference: In quran.com-frontend-next, keep concise “why” comments for analytics/UX decision points (e.g., guest vs enrolled click handlers) but avoid verbose JSDoc that repeats params/types. Convert multi-line JSDoc to brief inline rationale comments, especially in src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx and similar analytics handlers.

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:20:48.459Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-11-25T13:20:48.459Z
Learning: Applies to **/*.{tsx,jsx} : Use appropriate dependency arrays in useEffect hooks

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-28T12:29:33.962Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T12:29:33.962Z
Learning: Applies to **/*.{tsx,jsx} : Flag unnecessary API calls in React - suggest caching with `useSWR`

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-28T12:30:50.691Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/pre-pr-review.mdc:0-0
Timestamp: 2025-11-28T12:30:50.691Z
Learning: Applies to **/*.{ts,tsx} : Require proper error handling with meaningful fallbacks

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-28T12:30:38.634Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/instructions/typescript.instructions.md:0-0
Timestamp: 2025-11-28T12:30:38.634Z
Learning: Applies to **/*.{ts,tsx} : Ensure error types are properly typed, not `any`

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:29:33.962Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T12:29:33.962Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Require proper error handling with meaningful fallbacks

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-28T12:30:50.691Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/pre-pr-review.mdc:0-0
Timestamp: 2025-11-28T12:30:50.691Z
Learning: Applies to **/*.{ts,tsx} : Handle error states with user-friendly messages in API and data handling

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-28T12:29:41.178Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/instructions/api-data.instructions.md:0-0
Timestamp: 2025-11-28T12:29:41.178Z
Learning: Applies to src/api.ts,src/hooks/**/*.ts,src/services/**/*.ts,src/utils/api/**/*.ts : Ensure meaningful error messages for users in API error handling

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-25T13:21:18.501Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/typescript.mdc:0-0
Timestamp: 2025-11-25T13:21:18.501Z
Learning: Implement proper error handling with custom error types in TypeScript

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-25T13:21:18.501Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/typescript.mdc:0-0
Timestamp: 2025-11-25T13:21:18.501Z
Learning: Applies to **/*.{ts,tsx,d.ts} : Use try-catch blocks with typed catch clauses in TypeScript

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-25T13:21:18.501Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/typescript.mdc:0-0
Timestamp: 2025-11-25T13:21:18.501Z
Learning: Applies to **/*.{ts,tsx,d.ts} : Avoid type assertions unless necessary in TypeScript

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-28T12:31:06.687Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T12:31:06.687Z
Learning: Applies to **/*.{ts,tsx} : Handle errors with meaningful fallbacks for async operations

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-28T12:29:41.178Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/instructions/api-data.instructions.md:0-0
Timestamp: 2025-11-28T12:29:41.178Z
Learning: Applies to src/api.ts,src/hooks/**/*.ts,src/services/**/*.ts,src/utils/api/**/*.ts : Require error states for all API-dependent components - flag blind trust in API responses

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-10-22T20:39:29.339Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: tests/integration/learning-plans/guest-access.spec.ts:3-5
Timestamp: 2025-10-22T20:39:29.339Z
Learning: Repository: quran/quran.com-frontend-next
Context: tests/integration/learning-plans/guest-access.spec.ts and similar focused integration tests
Learning: For focused integration tests that validate specific route behavior, maintainers prefer hard-coded route paths (e.g., LP_URL, FIRST_LESSON_URL) over environment-based URLs to avoid unnecessary complexity.

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:31:06.687Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T12:31:06.687Z
Learning: Add tests for new functionality

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-25T13:20:48.459Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-11-25T13:20:48.459Z
Learning: Applies to **/*.{test,spec}.{tsx,jsx} : Implement integration tests for complex React flows

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-28T12:30:50.691Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/pre-pr-review.mdc:0-0
Timestamp: 2025-11-28T12:30:50.691Z
Learning: Applies to **/*.test.{ts,tsx} : New functionality needs tests

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-28T12:29:33.962Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T12:29:33.962Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Ensure test coverage for edge cases and error scenarios

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-11-28T12:30:50.691Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/pre-pr-review.mdc:0-0
Timestamp: 2025-11-28T12:30:50.691Z
Learning: Applies to **/*.test.{ts,tsx} : Cover edge cases and error scenarios in tests

Applied to files:

  • src/hooks/auth/useEnrollUser.ts
📚 Learning: 2025-10-22T20:42:09.214Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx:35-59
Timestamp: 2025-10-22T20:42:09.214Z
Learning: Preference for quran.com-frontend-next: keep single-use, page-specific components inline. Example: NotEnrolledMessage in src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx should remain inline; extract only if reused elsewhere.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-10-22T20:51:18.747Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:26-27
Timestamp: 2025-10-22T20:51:18.747Z
Learning: Analytics naming convention in quran.com-frontend-next: For syllabus day clicks, retain the legacy event name 'course_syllabus_day' for logged-in users to preserve existing dashboards; only guest flows introduce the 'guest_' prefix (e.g., 'guest_course_syllabus_day'). Apply concise inline "why" comments near such analytics decisions to prevent accidental renaming.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-24T11:52:10.333Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2589
File: src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx:24-33
Timestamp: 2025-11-24T11:52:10.333Z
Learning: In quran.com-frontend-next, DataFetcher's onFetchSuccess prop is typed as (data: BaseResponse) => void, but privateFetcher can return unwrapped types (e.g., Lesson) at runtime. Components using privateFetcher with onFetchSuccess may annotate callbacks as (data: any) => void to bridge this type mismatch, then treat the parameter as the actual returned type inside the callback body.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:30:38.634Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/instructions/typescript.instructions.md:0-0
Timestamp: 2025-11-28T12:30:38.634Z
Learning: Applies to **/*.{ts,tsx} : Flag any usage of `any` type - suggest `unknown` or specific types instead

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:21:18.501Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/typescript.mdc:0-0
Timestamp: 2025-11-25T13:21:18.501Z
Learning: Applies to **/*.{ts,tsx,d.ts} : Avoid using `any`, prefer `unknown` for unknown types in TypeScript

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:29:33.962Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T12:29:33.962Z
Learning: Applies to **/*.{ts,tsx} : Flag usage of `any` type in TypeScript - prefer `unknown` or specific types

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:31:06.687Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T12:31:06.687Z
Learning: Applies to **/*.{ts,tsx} : Use explicit types instead of `any` type without justification

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:30:50.691Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/pre-pr-review.mdc:0-0
Timestamp: 2025-11-28T12:30:50.691Z
Learning: Applies to **/*.{ts,tsx} : Flag any `any` types - use `unknown` or specific types instead

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:30:50.691Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/pre-pr-review.mdc:0-0
Timestamp: 2025-11-28T12:30:50.691Z
Learning: Applies to **/*.tsx : Use useSWR for data fetching, not raw fetch in React components

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:20:09.790Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/next-js-conventions.mdc:0-0
Timestamp: 2025-11-25T13:20:09.790Z
Learning: Applies to **/*.{ts,js,jsx,tsx} : Avoid using 'use client' for data fetching or state management

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:30:50.691Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/pre-pr-review.mdc:0-0
Timestamp: 2025-11-28T12:30:50.691Z
Learning: Applies to **/*.{ts,tsx} : Provide fallbacks for API responses - don't blindly trust data

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:29:33.962Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T12:29:33.962Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Ensure complex logic has inline comments explaining 'why'

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:30:50.691Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/pre-pr-review.mdc:0-0
Timestamp: 2025-11-28T12:30:50.691Z
Learning: Applies to **/*.tsx : Use proper memoization (useCallback, useMemo) for callbacks and expensive computations in React components

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:21:18.501Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/typescript.mdc:0-0
Timestamp: 2025-11-25T13:21:18.501Z
Learning: Applies to **/*.{ts,tsx,d.ts} : Use arrow functions for callbacks and methods in TypeScript

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:30:01.385Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/instructions/react-components.instructions.md:0-0
Timestamp: 2025-11-28T12:30:01.385Z
Learning: Applies to src/components/**/*.tsx,src/pages/**/*.tsx : Require `useCallback` for functions passed to child components

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:29:33.962Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T12:29:33.962Z
Learning: Applies to **/*.{tsx,jsx} : Flag unnecessary `useEffect` usage in React

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:19:57.738Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/next-js-app-router-rule.mdc:0-0
Timestamp: 2025-11-25T13:19:57.738Z
Learning: Applies to app/**/*.tsx : Follow Next.js documentation for best practices in data fetching, rendering, and routing when working with App Router components

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:20:09.790Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/next-js-conventions.mdc:0-0
Timestamp: 2025-11-25T13:20:09.790Z
Learning: Refer to Next.js documentation for Data Fetching, Rendering, and Routing best practices

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:18:33.501Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T13:18:33.501Z
Learning: Applies to src/pages/**/*.{ts,tsx} : Use Next.js 14 with Pages Router (not App Router)

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:19:57.738Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/next-js-app-router-rule.mdc:0-0
Timestamp: 2025-11-25T13:19:57.738Z
Learning: Be an expert in Next.js Pages Router best practices

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:31:06.687Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T12:31:06.687Z
Learning: Applies to src/pages/**/*.{ts,tsx} : Use Next.js 14 with Pages Router (NOT App Router) as the framework

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:20:09.790Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/next-js-conventions.mdc:0-0
Timestamp: 2025-11-25T13:20:09.790Z
Learning: Applies to **/*.{ts,js,jsx,tsx} : Rely on Next.js Pages Router for state changes

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:18:33.501Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T13:18:33.501Z
Learning: Applies to src/pages/**/*.{ts,tsx} : Protect routes using withAuth HOC

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:29:33.962Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T12:29:33.962Z
Learning: Applies to **/*.{tsx,jsx,ts,js} : Ensure proper authentication checks for protected routes

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-09-21T18:32:41.811Z
Learnt from: mohsinayoob
Repo: quran/quran.com-frontend-next PR: 2495
File: src/pages/logout.tsx:12-17
Timestamp: 2025-09-21T18:32:41.811Z
Learning: In the Next.js codebase, redirect-only pages like src/pages/logout.tsx intentionally use GetServerSidePropsResult<any> in JSDoc comments because they only perform server-side redirects without passing meaningful data to client-side rendering.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-09-19T13:59:31.762Z
Learnt from: mohsinayoob
Repo: quran/quran.com-frontend-next PR: 2495
File: src/pages/auth.tsx:143-149
Timestamp: 2025-09-19T13:59:31.762Z
Learning: In this Next.js codebase, the pattern of returning both `props: {}` and `redirect` together from getServerSideProps works correctly and is used consistently throughout multiple files including src/pages/auth.tsx and src/pages/logout.tsx. The Next.js runtime appears to ignore empty props when redirect is present.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
🧬 Code graph analysis (1)
src/hooks/auth/useEnrollUser.ts (3)
src/utils/auth/login.ts (1)
  • isLoggedIn (17-17)
src/utils/auth/api.ts (1)
  • enrollUser (457-464)
src/lib/sentry.ts (1)
  • logErrorToSentry (123-152)

…nents. Consolidate enrollment handling into a single function, improve user navigation for guest users, and enhance error handling. Update button rendering logic for better clarity and user experience.
Copy link
Contributor

@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: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bbcacb3 and 99b6293.

📒 Files selected for processing (2)
  • src/components/Course/CourseDetails/StatusHeader/index.tsx (3 hunks)
  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx (3 hunks)
🧰 Additional context used
📓 Path-based instructions (20)
src/pages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

src/pages/**/*.{ts,tsx}: Use Next.js 14 with Pages Router (not App Router)
Protect routes using withAuth HOC

Use Next.js 14 with Pages Router (NOT App Router) as the framework

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript with strict configuration
Use path alias @/ for src/ and @/dls/* for design system components

**/*.{ts,tsx}: Flag usage of any type in TypeScript - prefer unknown or specific types
Require explicit return types for public/exported functions in TypeScript
Prefer interface over type for object definitions in TypeScript
Use type for unions, intersections, and mapped types in TypeScript
Require enums for repeated raw values of the same category in TypeScript

**/*.{ts,tsx}: Flag any usage of any type - suggest unknown or specific types instead
Require explicit return types for all exported/public functions
Flag implicit any in function parameters
Ensure strict null checks are handled properly
Prefer interface for object shape definitions
Use type only for unions, intersections, and mapped types
Flag type usage where interface is more appropriate
Require enums when the same raw values appear multiple times
Flag repeated string/number literals that should be enums
Use PascalCase for types, interfaces, enums, and components
Use camelCase for variables, functions, and methods
Use UPPER_SNAKE_CASE for constants
Prefix Props interfaces with component name: ButtonProps, ModalProps
Flag unhandled Promise rejections
Require try-catch blocks for async operations
Ensure error types are properly typed, not any
Flag unused imports
Ensure imports are alphabetized within groups
Group import order: React → External packages → Internal modules → Types

**/*.{ts,tsx}: Flag any any types - use unknown or specific types instead
Require explicit return types on exported functions
Use interfaces for object shapes, types for unions in TypeScript
Use enums for repeated categorical values in TypeScript
Functions should be under 30 lines
Flag duplicated code - extract to reusable functions (DRY principle)
Require proper error handling with meaningful fallbacks
Flag unused imports, variables, or dead code
Comments shou...

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use API utilities from src/utils/auth/api.ts for authenticated requests

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
**/*.*

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

Add comments starting with 'TODO:' to outline problems or bugs encountered in existing code

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

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

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

**/*.*: Only modify sections of the code related to the task at hand
Avoid modifying unrelated pieces of code
Accomplish goals with minimal code changes

**/*.*: 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/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
**/*.{js,ts,jsx,tsx,java,py,cs,cpp,c,go,rb,php}

📄 CodeRabbit inference engine (.cursor/rules/clean-code.mdc)

**/*.{js,ts,jsx,tsx,java,py,cs,cpp,c,go,rb,php}: Replace hard-coded values with named constants and use descriptive constant names that explain the value's purpose
Keep constants at the top of the file or in a dedicated constants file
Variables, functions, and classes should reveal their purpose with meaningful names that explain why something exists and how it's used
Avoid abbreviations in names unless they're universally understood
Use comments to explain why something is done a certain way, not what the code does - make the code self-documenting
Document APIs, complex algorithms, and non-obvious side effects in comments
Each function should do exactly one thing and be small and focused
If a function needs a comment to explain what it does, it should be split into smaller, more focused functions
Extract repeated code into reusable functions and share common logic through proper abstraction
Keep related code together and organize code in a logical hierarchy
Hide implementation details and expose clear interfaces through encapsulation
Move nested conditionals into well-named functions for better readability

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
**/*.{ts,js,jsx,tsx}

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

**/*.{ts,js,jsx,tsx}: Rely on Next.js Pages Router for state changes
Prioritize Web Vitals (LCP, CLS, FID) in performance optimization
Minimize 'use client' usage - prefer server components and Next.js SSR features
Use 'use client' only for Web API access in small components
Avoid using 'use client' for data fetching or state management

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/performance-optimization-rules.mdc)

Optimize Web Vitals (LCP, CLS, FID) in JavaScript and TypeScript files

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/performance-optimization-rules.mdc)

Use dynamic loading for non-critical components using @src/components/dls/Spinner/Spinner.tsx

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
**/*.{tsx,jsx}

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

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

**/*.{tsx,jsx}: Require functional components only (...

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
src/**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/redux-toolkit-best-practices.mdc)

src/**/*.tsx: Use selectors for accessing state in components
Use Redux hooks (useSelector, useDispatch) in components

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
**/*.{ts,tsx,d.ts}

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

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

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
**/*.tsx

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

Prefix React component prop interfaces with 'Props' (e.g., ButtonProps) in TypeScript

**/*.tsx: Use functional components only - no class components in React
Props interface must be defined for React components
Use proper memoization (useCallback, useMemo) for callbacks and expensive computations in React components
Flag unnecessary useEffect - prefer event handlers or derived state in React components
Require skeleton loaders for async data to prevent layout shifts in React components
Use useSWR for data fetching, not raw fetch in React components
Use optimistic updates for predictable actions (bookmark, like) in React components
No hardcoded strings in UI
Use semantic HTML elements in React components
Add ARIA attributes where needed for accessibility in React components
Ensure keyboard navigation works in React components

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx,js,jsx}: Flag functions exceeding 30 lines - should be split
Identify duplicated code that should be extracted to reusable functions (DRY principle)
Flag unused imports, variables, or dead code
Require proper error handling with meaningful fallbacks
Flag skipped linting rules without clear justification
Ensure complex logic has inline comments explaining 'why'
Ensure environment variables are used for configuration instead of hardcoded values
Flag missing input validation or sanitization
Flag undocumented complex business logic

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
**/*.{tsx,jsx,ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{tsx,jsx,ts,js}: Flag hardcoded strings that should be localized
Ensure proper authentication checks for protected routes

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
**/*.{tsx,jsx,css,module.css}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Ensure RTL (right-to-left) support is maintained

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
**/*.{ts,tsx,js,jsx,json,env,yml,yaml}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Flag any hardcoded credentials or secrets

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
{src/components,src/pages}/**/*.tsx

📄 CodeRabbit inference engine (.github/instructions/localization.instructions.md)

{src/components,src/pages}/**/*.tsx: Flag ALL hardcoded user-facing strings - must use next-translate hook for text content
Use descriptive, hierarchical key names for translation keys and group related translations under common prefixes
Ensure interpolation is used for dynamic values in translations instead of string concatenation
Flag string concatenation with translated text - use translation interpolation instead

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.github/instructions/security.instructions.md)

**/*.{ts,tsx,js}: Flag ANY hardcoded credentials, API keys, or secrets in TypeScript/JavaScript code
Ensure all sensitive values use environment variables instead of hardcoding
Use NEXT_PUBLIC_ prefix only for client-side variables in environment variable declarations
Flag sensitive data exposed to client-side code
Require validation for all user inputs in TypeScript/JavaScript code
Flag direct usage of user input without sanitization, particularly with dangerouslySetInnerHTML
Ensure proper encoding for dynamic content to prevent injection attacks
Flag protected routes without auth checks in Next.js applications
Ensure proper session validation for authenticated requests
Flag sensitive operations without authentication checks

Files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
src/components/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

src/components/**/*.{ts,tsx}: Use React 18 functional components
Organize React components by feature in src/components/
Use TypeScript interfaces for props in functional components

src/components/**/*.{ts,tsx}: Use next-translate with t() for all user-facing text
Use Radix UI primitives for UI components
Use semantic HTML and ARIA attributes for accessibility
Use functional components only (no class components)

Files:

  • src/components/Course/CourseDetails/StatusHeader/index.tsx
src/components/**/*.tsx

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

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

Files:

  • src/components/Course/CourseDetails/StatusHeader/index.tsx
🧠 Learnings (40)
📓 Common learnings
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx:35-59
Timestamp: 2025-10-22T20:42:09.214Z
Learning: Preference for quran.com-frontend-next: keep single-use, page-specific components inline. Example: NotEnrolledMessage in src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx should remain inline; extract only if reused elsewhere.
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:26-27
Timestamp: 2025-10-22T20:51:18.747Z
Learning: Analytics naming convention in quran.com-frontend-next: For syllabus day clicks, retain the legacy event name 'course_syllabus_day' for logged-in users to preserve existing dashboards; only guest flows introduce the 'guest_' prefix (e.g., 'guest_course_syllabus_day'). Apply concise inline "why" comments near such analytics decisions to prevent accidental renaming.
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: tests/integration/learning-plans/guest-access.spec.ts:3-5
Timestamp: 2025-10-22T20:39:29.339Z
Learning: Repository: quran/quran.com-frontend-next
Context: tests/integration/learning-plans/guest-access.spec.ts and similar focused integration tests
Learning: For focused integration tests that validate specific route behavior, maintainers prefer hard-coded route paths (e.g., LP_URL, FIRST_LESSON_URL) over environment-based URLs to avoid unnecessary complexity.
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:44-49
Timestamp: 2025-10-22T20:33:55.176Z
Learning: Preference: In quran.com-frontend-next, keep concise “why” comments for analytics/UX decision points (e.g., guest vs enrolled click handlers) but avoid verbose JSDoc that repeats params/types. Convert multi-line JSDoc to brief inline rationale comments, especially in src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx and similar analytics handlers.
📚 Learning: 2025-10-22T20:42:09.214Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx:35-59
Timestamp: 2025-10-22T20:42:09.214Z
Learning: Preference for quran.com-frontend-next: keep single-use, page-specific components inline. Example: NotEnrolledMessage in src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx should remain inline; extract only if reused elsewhere.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
📚 Learning: 2025-10-22T20:33:55.176Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:44-49
Timestamp: 2025-10-22T20:33:55.176Z
Learning: Preference: In quran.com-frontend-next, keep concise “why” comments for analytics/UX decision points (e.g., guest vs enrolled click handlers) but avoid verbose JSDoc that repeats params/types. Convert multi-line JSDoc to brief inline rationale comments, especially in src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx and similar analytics handlers.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
📚 Learning: 2025-10-22T20:39:29.339Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: tests/integration/learning-plans/guest-access.spec.ts:3-5
Timestamp: 2025-10-22T20:39:29.339Z
Learning: Repository: quran/quran.com-frontend-next
Context: tests/integration/learning-plans/guest-access.spec.ts and similar focused integration tests
Learning: For focused integration tests that validate specific route behavior, maintainers prefer hard-coded route paths (e.g., LP_URL, FIRST_LESSON_URL) over environment-based URLs to avoid unnecessary complexity.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
📚 Learning: 2025-11-24T11:52:10.333Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2589
File: src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx:24-33
Timestamp: 2025-11-24T11:52:10.333Z
Learning: In quran.com-frontend-next, DataFetcher's onFetchSuccess prop is typed as (data: BaseResponse) => void, but privateFetcher can return unwrapped types (e.g., Lesson) at runtime. Components using privateFetcher with onFetchSuccess may annotate callbacks as (data: any) => void to bridge this type mismatch, then treat the parameter as the actual returned type inside the callback body.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:30:38.634Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/instructions/typescript.instructions.md:0-0
Timestamp: 2025-11-28T12:30:38.634Z
Learning: Applies to **/*.{ts,tsx} : Flag any usage of `any` type - suggest `unknown` or specific types instead

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:21:18.501Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/typescript.mdc:0-0
Timestamp: 2025-11-25T13:21:18.501Z
Learning: Applies to **/*.{ts,tsx,d.ts} : Avoid using `any`, prefer `unknown` for unknown types in TypeScript

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:30:38.634Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/instructions/typescript.instructions.md:0-0
Timestamp: 2025-11-28T12:30:38.634Z
Learning: Applies to **/*.{ts,tsx} : Ensure error types are properly typed, not `any`

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:29:33.962Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T12:29:33.962Z
Learning: Applies to **/*.{ts,tsx} : Flag usage of `any` type in TypeScript - prefer `unknown` or specific types

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:30:50.691Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/pre-pr-review.mdc:0-0
Timestamp: 2025-11-28T12:30:50.691Z
Learning: Applies to **/*.tsx : Use useSWR for data fetching, not raw fetch in React components

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:31:06.687Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T12:31:06.687Z
Learning: Applies to **/*.{ts,tsx} : Use explicit types instead of `any` type without justification

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:30:50.691Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/pre-pr-review.mdc:0-0
Timestamp: 2025-11-28T12:30:50.691Z
Learning: Applies to **/*.{ts,tsx} : Flag any `any` types - use `unknown` or specific types instead

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:20:09.790Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/next-js-conventions.mdc:0-0
Timestamp: 2025-11-25T13:20:09.790Z
Learning: Applies to **/*.{ts,js,jsx,tsx} : Avoid using 'use client' for data fetching or state management

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:30:50.691Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/pre-pr-review.mdc:0-0
Timestamp: 2025-11-28T12:30:50.691Z
Learning: Applies to **/*.{ts,tsx} : Provide fallbacks for API responses - don't blindly trust data

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-10-22T20:51:18.747Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:26-27
Timestamp: 2025-10-22T20:51:18.747Z
Learning: Analytics naming convention in quran.com-frontend-next: For syllabus day clicks, retain the legacy event name 'course_syllabus_day' for logged-in users to preserve existing dashboards; only guest flows introduce the 'guest_' prefix (e.g., 'guest_course_syllabus_day'). Apply concise inline "why" comments near such analytics decisions to prevent accidental renaming.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
  • src/components/Course/CourseDetails/StatusHeader/index.tsx
📚 Learning: 2025-11-28T12:29:33.962Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T12:29:33.962Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Ensure complex logic has inline comments explaining 'why'

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:21:18.501Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/typescript.mdc:0-0
Timestamp: 2025-11-25T13:21:18.501Z
Learning: Applies to **/*.{ts,tsx,d.ts} : Use arrow functions for callbacks and methods in TypeScript

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:30:50.691Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/pre-pr-review.mdc:0-0
Timestamp: 2025-11-28T12:30:50.691Z
Learning: Applies to **/*.tsx : Use proper memoization (useCallback, useMemo) for callbacks and expensive computations in React components

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:30:01.385Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/instructions/react-components.instructions.md:0-0
Timestamp: 2025-11-28T12:30:01.385Z
Learning: Applies to src/components/**/*.tsx,src/pages/**/*.tsx : Require `useCallback` for functions passed to child components

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:29:33.962Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T12:29:33.962Z
Learning: Applies to **/*.{tsx,jsx} : Ensure proper memoization with `useMemo` and `useCallback` where appropriate in React

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:29:33.962Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T12:29:33.962Z
Learning: Applies to **/*.{tsx,jsx} : Flag unnecessary `useEffect` usage in React

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:21:18.501Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/typescript.mdc:0-0
Timestamp: 2025-11-25T13:21:18.501Z
Learning: Applies to **/*.{ts,tsx,d.ts} : Handle Promise rejections properly in TypeScript

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:30:38.634Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/instructions/typescript.instructions.md:0-0
Timestamp: 2025-11-28T12:30:38.634Z
Learning: Applies to **/*.{ts,tsx} : Flag unhandled Promise rejections

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:30:50.691Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/pre-pr-review.mdc:0-0
Timestamp: 2025-11-28T12:30:50.691Z
Learning: Applies to **/*.{ts,tsx} : Require proper error handling with meaningful fallbacks

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:29:33.962Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T12:29:33.962Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Require proper error handling with meaningful fallbacks

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:30:38.634Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/instructions/typescript.instructions.md:0-0
Timestamp: 2025-11-28T12:30:38.634Z
Learning: Applies to **/*.{ts,tsx} : Require try-catch blocks for async operations

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:31:06.687Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T12:31:06.687Z
Learning: Applies to **/*.{ts,tsx} : Handle errors with meaningful fallbacks for async operations

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:20:48.459Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-11-25T13:20:48.459Z
Learning: Applies to **/*.{tsx,jsx} : Handle async errors properly in React components

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:19:57.738Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/next-js-app-router-rule.mdc:0-0
Timestamp: 2025-11-25T13:19:57.738Z
Learning: Applies to app/**/*.tsx : Follow Next.js documentation for best practices in data fetching, rendering, and routing when working with App Router components

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:20:09.790Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/next-js-conventions.mdc:0-0
Timestamp: 2025-11-25T13:20:09.790Z
Learning: Refer to Next.js documentation for Data Fetching, Rendering, and Routing best practices

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:18:33.501Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T13:18:33.501Z
Learning: Applies to src/pages/**/*.{ts,tsx} : Use Next.js 14 with Pages Router (not App Router)

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-28T12:31:06.687Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T12:31:06.687Z
Learning: Applies to src/pages/**/*.{ts,tsx} : Use Next.js 14 with Pages Router (NOT App Router) as the framework

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:19:57.738Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/next-js-app-router-rule.mdc:0-0
Timestamp: 2025-11-25T13:19:57.738Z
Learning: Be an expert in Next.js Pages Router best practices

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:20:09.790Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/next-js-conventions.mdc:0-0
Timestamp: 2025-11-25T13:20:09.790Z
Learning: Applies to **/*.{ts,js,jsx,tsx} : Rely on Next.js Pages Router for state changes

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-11-25T13:18:33.501Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T13:18:33.501Z
Learning: Applies to src/pages/**/*.{ts,tsx} : Protect routes using withAuth HOC

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-09-21T18:32:41.811Z
Learnt from: mohsinayoob
Repo: quran/quran.com-frontend-next PR: 2495
File: src/pages/logout.tsx:12-17
Timestamp: 2025-09-21T18:32:41.811Z
Learning: In the Next.js codebase, redirect-only pages like src/pages/logout.tsx intentionally use GetServerSidePropsResult<any> in JSDoc comments because they only perform server-side redirects without passing meaningful data to client-side rendering.

Applied to files:

  • src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx
📚 Learning: 2025-10-26T03:27:28.728Z
Learnt from: afifvdin
Repo: quran/quran.com-frontend-next PR: 2545
File: src/pages/reading-goal/index.tsx:31-35
Timestamp: 2025-10-26T03:27:28.728Z
Learning: In src/pages/reading-goal/index.tsx, the initialExampleKey is intentionally computed only when isLoggedIn() is true. This is by design: guest users can interact with the page and select options manually, but the example URL parameter only pre-selects an option for logged-in users (typically after being redirected back from login). The example selection is preserved through the authentication redirect flow.

Applied to files:

  • src/components/Course/CourseDetails/StatusHeader/index.tsx
📚 Learning: 2025-09-21T19:00:54.303Z
Learnt from: mohsinayoob
Repo: quran/quran.com-frontend-next PR: 2495
File: src/pages/logout.tsx:11-12
Timestamp: 2025-09-21T19:00:54.303Z
Learning: In src/pages/logout.tsx, the developer mohsinayoob prefers to let decodeURIComponent exceptions bubble up to the global catch block rather than handling them locally. This ensures centralized error handling where all logout errors redirect to a safe default path, maintaining consistent fallback behavior instead of having multiple error handling points.

Applied to files:

  • src/components/Course/CourseDetails/StatusHeader/index.tsx
📚 Learning: 2025-11-28T12:29:41.178Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .github/instructions/api-data.instructions.md:0-0
Timestamp: 2025-11-28T12:29:41.178Z
Learning: Applies to src/api.ts,src/hooks/**/*.ts,src/services/**/*.ts,src/utils/api/**/*.ts : Require optimistic updates for predictable actions (like, bookmark, etc.) using mutate with optimisticData

Applied to files:

  • src/components/Course/CourseDetails/StatusHeader/index.tsx
📚 Learning: 2025-12-01T07:32:06.462Z
Learnt from: afifvdin
Repo: quran/quran.com-frontend-next PR: 2608
File: src/components/HeaderNavigation/index.tsx:18-18
Timestamp: 2025-12-01T07:32:06.462Z
Learning: In src/components/HeaderNavigation/index.tsx, the team prefers using JavaScript-based responsive logic (useIsMobile() hook) for button sizing over CSS media queries, despite potential SSR hydration considerations.

Applied to files:

  • src/components/Course/CourseDetails/StatusHeader/index.tsx
🧬 Code graph analysis (2)
src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx (3)
src/utils/navigation.ts (2)
  • getLoginNavigationUrl (405-406)
  • getLessonNavigationUrl (355-356)
types/auth/Course.ts (2)
  • Lesson (3-16)
  • Course (29-48)
src/utils/auth/apiPaths.ts (1)
  • makeGetCourseUrl (145-145)
src/components/Course/CourseDetails/StatusHeader/index.tsx (6)
src/components/dls/Toast/Toast.tsx (1)
  • useToast (86-96)
src/utils/auth/login.ts (2)
  • isLoggedIn (17-17)
  • getUserType (24-27)
src/utils/auth/apiPaths.ts (1)
  • makeGetCourseUrl (145-145)
types/auth/Course.ts (1)
  • Course (29-48)
src/utils/navigation.ts (2)
  • getLessonNavigationUrl (355-356)
  • getCourseNavigationUrl (346-347)
src/utils/eventLogger.ts (1)
  • logButtonClick (44-46)
🔇 Additional comments (8)
src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx (4)

1-1: LGTM! Imports correctly support the auto-enrollment flow.

All added imports are used and necessary for the enrollment feature implementation.

Also applies to: 9-10, 13-14, 16-17


27-28: LGTM! Hooks are correctly initialized.

Using useMutateWithoutRevalidation is appropriate for optimistic cache updates after enrollment.


30-37: LGTM! Error handling correctly redirects unauthenticated users.

The updated navigation flow properly uses utility functions to redirect to login with the current lesson URL as the redirect target.


82-82: LGTM! DataFetcher prop correctly wires auto-enrollment.

The onFetchSuccess callback properly triggers enrollment when lesson data is successfully fetched.

src/components/Course/CourseDetails/StatusHeader/index.tsx (4)

14-17: LGTM - Import changes align with new enrollment flow.

The new imports for useEnrollUser and EnrollmentMethod properly support the unified enrollment approach, replacing the previous guest enrollment mechanism.


32-40: LGTM - Component setup is clean and addresses past feedback.

The removal of title from destructuring resolves the previously flagged dead code issue. The hook setup properly initializes the new enrollUserInCourse function.


63-80: LGTM - Clear branching logic for enrollment flow.

The function correctly handles all user states:

  • Guest with allowGuestAccess: navigates directly to first lesson
  • Guest without access: redirects to login with return URL
  • Logged-in user: proceeds with enrollment

The early return pattern and analytics logging follow project conventions.


82-108: LGTM - Well-structured render logic with DRY principle.

Extracting startButton as a reusable element eliminates duplication. The conditional rendering uses clean early returns, and returning null for enrolled users in CTA mode is appropriate.

@osamasayed osamasayed removed their request for review December 2, 2025 17:46
@yousefdergham yousefdergham self-assigned this Dec 3, 2025
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