Skip to content

feat: add doctor avatars and image to empowerment section - #141

Merged
Smartlify07 merged 23 commits into
mainfrom
feat/landing-page-animations
Aug 9, 2026
Merged

feat: add doctor avatars and image to empowerment section#141
Smartlify07 merged 23 commits into
mainfrom
feat/landing-page-animations

Conversation

@Smartlify07

@Smartlify07 Smartlify07 commented Aug 9, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add doctor avatar images (M-Anderson, A-Rivera) to the Never Navigate Alone card using the shared Avatar component
  • Add \girl-with-phone.png\ image to the Build Independence card
  • Center card content and reposition course badges

Verification


  • px tsc --noEmit\ clean

Summary by CodeRabbit

  • New Features

    • Added a redesigned donation form with validation, fee and total calculations, payment checkout, loading states, and error handling.
    • Donation checkout and success pages now display totals including the 3% administration fee.
    • Enhanced empowerment content with profile imagery and updated course previews.
  • UI Improvements

    • Refined responsive layouts, spacing, sizing, typography, and button styling across marketing and dashboard pages.
    • Improved course cards, donation hero content, and navigation presentation.
  • Bug Fixes

    • Improved unexpected error logging while preserving generic error responses.

# Conflicts:
#	src/features/marketing/components/donation-support-section.tsx
@vercel

vercel Bot commented Aug 9, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
modern-advocates Building Building Preview Aug 9, 2026 7:02am

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 16a6029e-7bd9-446b-b5cb-0499ae736563

📥 Commits

Reviewing files that changed from the base of the PR and between 1919d5e and b29b231.

⛔ Files ignored due to path filters (3)
  • public/figma-home/A-Rivera.png is excluded by !**/*.png
  • public/figma-home/M-Anderson.png is excluded by !**/*.png
  • public/figma-home/girl-with-phone.png is excluded by !**/*.png
📒 Files selected for processing (37)
  • src/app/(marketing)/donation/success/page.tsx
  • src/app/(user)/dashboard/page.tsx
  • src/app/api/donations/route.ts
  • src/app/globals.css
  • src/features/courses/components/course-card.tsx
  • src/features/courses/components/enroll-now-button.tsx
  • src/features/marketing/components/about-hero-section.tsx
  • src/features/marketing/components/about-our-values-section.tsx
  • src/features/marketing/components/about-support-mission-section.tsx
  • src/features/marketing/components/community-section.tsx
  • src/features/marketing/components/contact-hero-section.tsx
  • src/features/marketing/components/course-detail-content-section.tsx
  • src/features/marketing/components/course-detail-hero-section.tsx
  • src/features/marketing/components/course-information-card.tsx
  • src/features/marketing/components/courses-hero-section.tsx
  • src/features/marketing/components/cta-section.tsx
  • src/features/marketing/components/donation-cta-section.tsx
  • src/features/marketing/components/donation-form.tsx
  • src/features/marketing/components/donation-hero-section.tsx
  • src/features/marketing/components/donation-support-section.tsx
  • src/features/marketing/components/empowerment-section.tsx
  • src/features/marketing/components/faq.tsx
  • src/features/marketing/components/footer.tsx
  • src/features/marketing/components/how-can-we-help.tsx
  • src/features/marketing/components/how-can-we-support.tsx
  • src/features/marketing/components/invest-in-hope-section.tsx
  • src/features/marketing/components/mission-sections.tsx
  • src/features/marketing/components/our-vision-section.tsx
  • src/features/marketing/components/practical-pathways-section.tsx
  • src/features/marketing/components/stories-from-our-community-section.tsx
  • src/features/marketing/components/testimonials.tsx
  • src/features/marketing/lib/donation-pricing.ts
  • src/features/user-dashboard/components/course-player-navbar.tsx
  • src/features/user-dashboard/components/dashboard-navbar.tsx
  • src/shared/lib/api-handler.ts
  • src/shared/ui/marketing-button.tsx
  • src/shared/ui/marketing-container.tsx

📝 Walkthrough

Walkthrough

The PR adds fee-inclusive donation pricing and a validated checkout form. It also centralizes marketing layout rules, updates responsive presentation across marketing and course pages, adjusts dashboard layouts, and adds API error logging.

Changes

Donation checkout flow

Layer / File(s) Summary
Donation pricing and submission
src/features/marketing/lib/donation-pricing.ts, src/features/marketing/components/donation-form.tsx, src/features/marketing/components/donation-support-section.tsx
Adds a 3% administrative fee, validated form fields, computed totals, checkout submission, loading state, and error handling.
Checkout total integration
src/app/api/donations/route.ts, src/app/(marketing)/donation/success/page.tsx
Uses the fee-inclusive total for Stripe amounts and success-page display formatting.

Shared marketing layout

Layer / File(s) Summary
Shared container rollout
src/app/globals.css, src/shared/ui/marketing-container.tsx, src/features/marketing/components/*, src/features/user-dashboard/components/*
Adds responsive .marketing-container rules and applies them across marketing sections and dashboard navigation.
Responsive section adjustments
src/features/marketing/components/contact-hero-section.tsx, src/features/marketing/components/course-detail-*.tsx, src/features/marketing/components/donation-hero-section.tsx, src/features/marketing/components/footer.tsx
Updates spacing, widths, grids, image sizing, footer columns, and selected typography.

Presentation and course updates

Layer / File(s) Summary
Marketing presentation
src/features/marketing/components/empowerment-section.tsx, src/features/marketing/components/courses-hero-section.tsx, src/shared/ui/marketing-button.tsx
Adds specialist avatars and preview imagery, changes course copy to “Trainings,” adjusts responsive card sizing, and updates solid button styling.
Course and dashboard presentation
src/app/(user)/dashboard/page.tsx, src/features/courses/components/*, src/features/user-dashboard/components/*
Adjusts grid alignment, card widths, enrollment button color, and dashboard navigation formatting.

API diagnostics

Layer / File(s) Summary
Unhandled error logging
src/shared/lib/api-handler.ts
Logs unhandled API errors before Sentry capture and the generic 500 response.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Donor
  participant DonationForm
  participant DonationsAPI
  participant Stripe
  participant DonationSuccessPage
  Donor->>DonationForm: Submit donation details
  DonationForm->>DonationsAPI: Send validated donation data
  DonationsAPI->>Stripe: Create checkout with fee-inclusive amount
  Stripe-->>DonationsAPI: Return checkout URL
  DonationsAPI-->>DonationForm: Return checkout URL
  DonationForm->>Stripe: Redirect to checkout
  Stripe-->>DonationSuccessPage: Return donation amount
  DonationSuccessPage->>DonationSuccessPage: Compute and format total
Loading

Possibly related PRs

Poem

A rabbit checks the fee with care,
Then sends the gift through checkout air.
New containers line the way,
Course cards hop into display.
Stripe lights the path ahead—
“Success!” the grateful bunny said.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main empowerment section changes, including the doctor avatars and image.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch feat/landing-page-animations
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/landing-page-animations

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.

…mations

# Conflicts:
#	src/features/marketing/components/about-support-mission-section.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`(user)/dashboard/page.tsx:
- Around line 76-80: Update the loading skeleton container in the dashboard card
map to use the same sm breakpoint maximum width as CourseCard.Root, changing the
current 300px constraint to the shared 400px width so the loading and loaded
layouts remain aligned.

In `@src/features/marketing/components/course-detail-content-section.tsx`:
- Around line 25-42: Extract the complete CourseContentData type from
course-detail-content-section.tsx into a shared module, then import and reuse it
in both the section component and CourseInformationCard. Ensure the shared
definition includes the full modules/topics and reviews shapes so the two
components cannot drift.

In `@src/features/marketing/components/donation-form.tsx`:
- Around line 100-102: Update the donation copy in the paragraph rendered by the
donation form to replace the period after “hope” with a comma, preserving the
rest of the sentence.
- Line 46: Update the donation form schema around confirmation to require a true
value, include confirmation in the onSubmit request body, and add matching
validation in the POST handler for /api/donations so missing or false
confirmation is rejected before creating a pending donation.

In `@src/features/marketing/components/empowerment-section.tsx`:
- Line 28: Add w-full to the three text wrapper elements in the empowerment
section, including the corresponding wrappers near the referenced locations, so
headings and descriptions span the card width and wrap correctly while
preserving the existing centered layout.
- Around line 69-72: Add alternative text to both AvatarImage instances in the
empowerment section: use alt="" because the adjacent doctor names already
identify the portraits, keeping the avatars decorative.
- Line 153: Update the overlay div in the empowerment section to replace the
arbitrary top-[14%] offset with an existing spacing design token or named layout
utility. Preserve the current positioning and styling while avoiding arbitrary
spacing values.

In `@src/features/marketing/lib/donation-pricing.ts`:
- Around line 3-9: Update computeAdminFee to convert the amount to integer cents
and calculate the fee using integer basis-point arithmetic before converting
back to dollars, ensuring half-cent values round correctly. Keep
computeDonationTotal using the corrected fee result and preserve its existing
cent-based total rounding.

In `@src/shared/lib/api-handler.ts`:
- Line 42: Replace the raw console.error(error) call in the API handler with the
project’s trusted redacting production logger, ensuring caught errors are logged
without exposing sensitive API, payment, email, enrollment, session, or Stripe
transaction fields.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 16a6029e-7bd9-446b-b5cb-0499ae736563

📥 Commits

Reviewing files that changed from the base of the PR and between 1919d5e and b29b231.

⛔ Files ignored due to path filters (3)
  • public/figma-home/A-Rivera.png is excluded by !**/*.png
  • public/figma-home/M-Anderson.png is excluded by !**/*.png
  • public/figma-home/girl-with-phone.png is excluded by !**/*.png
📒 Files selected for processing (37)
  • src/app/(marketing)/donation/success/page.tsx
  • src/app/(user)/dashboard/page.tsx
  • src/app/api/donations/route.ts
  • src/app/globals.css
  • src/features/courses/components/course-card.tsx
  • src/features/courses/components/enroll-now-button.tsx
  • src/features/marketing/components/about-hero-section.tsx
  • src/features/marketing/components/about-our-values-section.tsx
  • src/features/marketing/components/about-support-mission-section.tsx
  • src/features/marketing/components/community-section.tsx
  • src/features/marketing/components/contact-hero-section.tsx
  • src/features/marketing/components/course-detail-content-section.tsx
  • src/features/marketing/components/course-detail-hero-section.tsx
  • src/features/marketing/components/course-information-card.tsx
  • src/features/marketing/components/courses-hero-section.tsx
  • src/features/marketing/components/cta-section.tsx
  • src/features/marketing/components/donation-cta-section.tsx
  • src/features/marketing/components/donation-form.tsx
  • src/features/marketing/components/donation-hero-section.tsx
  • src/features/marketing/components/donation-support-section.tsx
  • src/features/marketing/components/empowerment-section.tsx
  • src/features/marketing/components/faq.tsx
  • src/features/marketing/components/footer.tsx
  • src/features/marketing/components/how-can-we-help.tsx
  • src/features/marketing/components/how-can-we-support.tsx
  • src/features/marketing/components/invest-in-hope-section.tsx
  • src/features/marketing/components/mission-sections.tsx
  • src/features/marketing/components/our-vision-section.tsx
  • src/features/marketing/components/practical-pathways-section.tsx
  • src/features/marketing/components/stories-from-our-community-section.tsx
  • src/features/marketing/components/testimonials.tsx
  • src/features/marketing/lib/donation-pricing.ts
  • src/features/user-dashboard/components/course-player-navbar.tsx
  • src/features/user-dashboard/components/dashboard-navbar.tsx
  • src/shared/lib/api-handler.ts
  • src/shared/ui/marketing-button.tsx
  • src/shared/ui/marketing-container.tsx

export function RestoreHopeCard() {
return (
<div className="relative flex h-120 w-full flex-col justify-between overflow-hidden rounded-2xl bg-[#ECE8FF] px-7.5 py-10">
<div className="relative flex h-120 w-full flex-col items-center justify-between overflow-hidden rounded-2xl bg-[#ECE8FF] px-7.5 py-10">

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep the card text wrappers at full width.

items-center applies to every direct child. The heading and description wrappers have no width class. They can shrink to max-content width instead of wrapping to the card width. Long descriptions can be clipped by overflow-hidden.

Add w-full to the three text wrappers, or center only the preview panels.

Also applies to: 53-53, 134-134

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/empowerment-section.tsx` at line 28, Add
w-full to the three text wrapper elements in the empowerment section, including
the corresponding wrappers near the referenced locations, so headings and
descriptions span the card width and wrap correctly while preserving the
existing centered layout.

Comment on lines +69 to +72
<Avatar className="size-12 shrink-0">
<AvatarImage src="/figma-home/M-Anderson.png" />
<AvatarFallback>MA</AvatarFallback>
</Avatar>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add alternative text handling for the avatar images.

AvatarImage renders an image element, but neither image supplies alt. Because each doctor name is already rendered beside the image, use alt="" for a decorative portrait or provide a meaningful description.

Also applies to: 98-101

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/empowerment-section.tsx` around lines 69 -
72, Add alternative text to both AvatarImage instances in the empowerment
section: use alt="" because the adjacent doctor names already identify the
portraits, keeping the avatars decorative.

Week 2: AI Productivity and Prompting
</h3>
<p className="text-[6px] text-primary">0/9 | 1 hr 30mins</p>{" "}
<div className="absolute top-[14%] -right-4 flex h-14 w-[174px] justify-between rounded-sm bg-white p-2.5">

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Replace the arbitrary overlay offset with a design token.

top-[14%] introduces an arbitrary spacing value in the changed layout. Use an existing spacing token or a named layout utility.

As per coding guidelines, do not use arbitrary hex colors or spacing; use the repository's design tokens.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/empowerment-section.tsx` at line 153,
Update the overlay div in the empowerment section to replace the arbitrary
top-[14%] offset with an existing spacing design token or named layout utility.
Preserve the current positioning and styling while avoiding arbitrary spacing
values.

Source: Coding guidelines

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`(user)/dashboard/page.tsx:
- Around line 76-80: Update the loading skeleton container in the dashboard card
map to use the same sm breakpoint maximum width as CourseCard.Root, changing the
current 300px constraint to the shared 400px width so the loading and loaded
layouts remain aligned.

In `@src/features/marketing/components/course-detail-content-section.tsx`:
- Around line 25-42: Extract the complete CourseContentData type from
course-detail-content-section.tsx into a shared module, then import and reuse it
in both the section component and CourseInformationCard. Ensure the shared
definition includes the full modules/topics and reviews shapes so the two
components cannot drift.

In `@src/features/marketing/components/donation-form.tsx`:
- Around line 100-102: Update the donation copy in the paragraph rendered by the
donation form to replace the period after “hope” with a comma, preserving the
rest of the sentence.
- Line 46: Update the donation form schema around confirmation to require a true
value, include confirmation in the onSubmit request body, and add matching
validation in the POST handler for /api/donations so missing or false
confirmation is rejected before creating a pending donation.

In `@src/features/marketing/components/empowerment-section.tsx`:
- Line 28: Add w-full to the three text wrapper elements in the empowerment
section, including the corresponding wrappers near the referenced locations, so
headings and descriptions span the card width and wrap correctly while
preserving the existing centered layout.
- Around line 69-72: Add alternative text to both AvatarImage instances in the
empowerment section: use alt="" because the adjacent doctor names already
identify the portraits, keeping the avatars decorative.
- Line 153: Update the overlay div in the empowerment section to replace the
arbitrary top-[14%] offset with an existing spacing design token or named layout
utility. Preserve the current positioning and styling while avoiding arbitrary
spacing values.

In `@src/features/marketing/lib/donation-pricing.ts`:
- Around line 3-9: Update computeAdminFee to convert the amount to integer cents
and calculate the fee using integer basis-point arithmetic before converting
back to dollars, ensuring half-cent values round correctly. Keep
computeDonationTotal using the corrected fee result and preserve its existing
cent-based total rounding.

In `@src/shared/lib/api-handler.ts`:
- Line 42: Replace the raw console.error(error) call in the API handler with the
project’s trusted redacting production logger, ensuring caught errors are logged
without exposing sensitive API, payment, email, enrollment, session, or Stripe
transaction fields.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 16a6029e-7bd9-446b-b5cb-0499ae736563

📥 Commits

Reviewing files that changed from the base of the PR and between 1919d5e and b29b231.

⛔ Files ignored due to path filters (3)
  • public/figma-home/A-Rivera.png is excluded by !**/*.png
  • public/figma-home/M-Anderson.png is excluded by !**/*.png
  • public/figma-home/girl-with-phone.png is excluded by !**/*.png
📒 Files selected for processing (37)
  • src/app/(marketing)/donation/success/page.tsx
  • src/app/(user)/dashboard/page.tsx
  • src/app/api/donations/route.ts
  • src/app/globals.css
  • src/features/courses/components/course-card.tsx
  • src/features/courses/components/enroll-now-button.tsx
  • src/features/marketing/components/about-hero-section.tsx
  • src/features/marketing/components/about-our-values-section.tsx
  • src/features/marketing/components/about-support-mission-section.tsx
  • src/features/marketing/components/community-section.tsx
  • src/features/marketing/components/contact-hero-section.tsx
  • src/features/marketing/components/course-detail-content-section.tsx
  • src/features/marketing/components/course-detail-hero-section.tsx
  • src/features/marketing/components/course-information-card.tsx
  • src/features/marketing/components/courses-hero-section.tsx
  • src/features/marketing/components/cta-section.tsx
  • src/features/marketing/components/donation-cta-section.tsx
  • src/features/marketing/components/donation-form.tsx
  • src/features/marketing/components/donation-hero-section.tsx
  • src/features/marketing/components/donation-support-section.tsx
  • src/features/marketing/components/empowerment-section.tsx
  • src/features/marketing/components/faq.tsx
  • src/features/marketing/components/footer.tsx
  • src/features/marketing/components/how-can-we-help.tsx
  • src/features/marketing/components/how-can-we-support.tsx
  • src/features/marketing/components/invest-in-hope-section.tsx
  • src/features/marketing/components/mission-sections.tsx
  • src/features/marketing/components/our-vision-section.tsx
  • src/features/marketing/components/practical-pathways-section.tsx
  • src/features/marketing/components/stories-from-our-community-section.tsx
  • src/features/marketing/components/testimonials.tsx
  • src/features/marketing/lib/donation-pricing.ts
  • src/features/user-dashboard/components/course-player-navbar.tsx
  • src/features/user-dashboard/components/dashboard-navbar.tsx
  • src/shared/lib/api-handler.ts
  • src/shared/ui/marketing-button.tsx
  • src/shared/ui/marketing-container.tsx
🛑 Comments failed to post (6)
src/app/(user)/dashboard/page.tsx (1)

76-80: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate files =="
fd -a 'page\.tsx$|course-card\.tsx$' . | sed 's#^\./##' | head -100

echo "== referenced dashboard file excerpt if present =="
if [ -f 'src/app/(user)/dashboard/page.tsx' ]; then
  nl -ba 'src/app/(user)/dashboard/page.tsx' | sed -n '60,95p'
fi

echo "== course card relevant excerpt if present =="
if [ -f 'src/features/courses/components/course-card.tsx' ]; then
  ast-grep outline 'src/features/courses/components/course-card.tsx' --view compact || true
  nl -ba 'src/features/courses/components/course-card.tsx' | sed -n '1,180p'
fi

Repository: Smartlify07/Modern-Advocates

Length of output: 2790


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Use awk because nl is unavailable in this sandbox.
awk='awk'
dashboard='src/app/(user)/dashboard/page.tsx'
coursecard='src/features/courses/components/course-card.tsx'

echo "== dashboard excerpt =="
if [ -f "$dashboard" ]; then
  $awk 'NR>=60 && NR<=95 { printf "%6d: %s\n", NR, $0 }' "$dashboard"
else
  echo "missing $dashboard"
fi

echo "== course-card excerpt =="
if [ -f "$coursecard" ]; then
  $awk 'NR>=1 && NR<=220 { printf "%6d: %s\n", NR, $0 }' "$coursecard"
else
  echo "missing $coursecard"
fi

echo "== max-width occurrences in relevant snippets =="
$awk '$0 ~ /max-w\[/ { printf "%s:%d: %s\n", FILENAME, NR, $0 }' "$dashboard" "$coursecard" 2>/dev/null

Repository: Smartlify07/Modern-Advocates

Length of output: 8021


Match the loading card width to the loaded card width.

The loading skeleton uses sm:max-w-[300px], while CourseCard.Root renders with sm:max-w-[400px]. If the grid grows wider than 300px, cards expand after the loading state, shifting the layout. Use the shared 400px maximum, or mark the 300px loading size as intentional.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(user)/dashboard/page.tsx around lines 76 - 80, Update the loading
skeleton container in the dashboard card map to use the same sm breakpoint
maximum width as CourseCard.Root, changing the current 300px constraint to the
shared 400px width so the loading and loaded layouts remain aligned.
src/features/marketing/components/course-detail-content-section.tsx (1)

25-42: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate candidate files =="
git ls-files | rg '(^|/)course-(detail-content-section|information-card)\.tsx$|(\.d\.ts$|course.*\.ts$)' || true

echo
echo "== course-detail-content-section outline and relevant lines =="
if [ -f src/features/marketing/components/course-detail-content-section.tsx ]; then
  wc -l src/features/marketing/components/course-detail-content-section.tsx
  sed -n '1,120p' src/features/marketing/components/course-detail-content-section.tsx | cat -n
fi

echo
echo "== course-information-card relevant definitions =="
if [ -f src/features/marketing/components/course-information-card.tsx ]; then
  rg -n "CourseContentData|export type|export interface|interface .*Course" src/features/marketing/components/course-information-card.tsx -C 4
fi

echo
echo "== CourseContentData references =="
rg -n "CourseContentData|CourseInformationData|CourseData|interface .*Course|type .*Course" src user-service shared features -S || true

echo
echo "== package lint/build references =="
git ls-files | rg 'package\.json$' || true
for f in $(git ls-files package*.json); do echo "--- $f"; sed -n '1,220p' "$f"; done

Repository: Smartlify07/Modern-Advocates

Length of output: 15706


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== file names =="
git ls-files | rg 'src/features/marketing/components/(course-detail-content-section|course-information-card)\.tsx$' || true

echo
echo "== course-detail-content-section imports and CourseContentData section =="
sed -n '1,80p' src/features/marketing/components/course-detail-content-section.tsx | cat -n

echo
echo "== course-information-card imports and CourseContentData/I interface section =="
sed -n '1,90p' src/features/marketing/components/course-information-card.tsx | cat -n

echo
echo "== exact CourseContentData references =="
rg -n "\bCourseContentData\b|interface CourseInformation|type CourseInformation|interface Course|type Course" src/features/marketing/components src -S || true

echo
echo "== deterministic AST-ish type-shape comparison from source (read-only text extraction only) =="
python3 - <<'PY'
from pathlib import Path
import re

files = [
    Path("src/features/marketing/components/course-detail-content-section.tsx"),
    Path("src/features/marketing/components/course-information-card.tsx"),
]
for path in files:
    text = path.read_text()
    start = text.find("export type CourseContentData")
    if start == -1:
        start = text.find("export interface CourseContentData")
    if start == -1:
        end = path.name + " has no CourseContentData"
    else:
        snippet = text[start:]
        brace = snippet.find("{")
        depth = 0
        end = 0
        for i, ch in enumerate(snippet):
            if ch == "{":
                depth += 1
            elif ch == "}":
                depth -= 1
                if depth == 0:
                    end = i + 1
                    break
        print(f"\n## {path}")
        print("\n".join(f"{idx+1}: {line}" for idx,line in enumerate(snippet[:end].splitlines())))
PY

Repository: Smartlify07/Modern-Advocates

Length of output: 9164


Use one CourseContentData definition.

src/features/marketing/components/course-detail-content-section.tsx defines the full course data shape and forwards it to CourseInformationCard, whose local CourseContentData only declares a smaller subset. The nested modules.topics type is not identical across the two files, so this can drift.

Extract CourseContentData to one shared module and use it consistently.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/course-detail-content-section.tsx` around
lines 25 - 42, Extract the complete CourseContentData type from
course-detail-content-section.tsx into a shared module, then import and reuse it
in both the section component and CourseInformationCard. Ensure the shared
definition includes the full modules/topics and reviews shapes so the two
components cannot drift.

Source: Coding guidelines

src/features/marketing/components/donation-form.tsx (2)

46-46: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate donation form and related files =="
fd -a 'donation-form\.tsx$|donation|route\.ts$|route\.tsx$' . | sed 's#^\./##' | head -200

echo
echo "== donation-form.tsx =="
file="$(fd 'donation-form\.tsx$' . | head -1)"
if [ -n "${file:-}" ]; then
  wc -l "$file"
  cat -n "$file"
fi

echo
echo "== search donation API endpoints/usages =="
rg -n "donation|confirmation|donorName|donorEmail|donationType" -S . \
  -g '!node_modules' -g '!dist' -g '!build' -g '!next' \
  -g '!*.lock' | head -300

Repository: Smartlify07/Modern-Advocates

Length of output: 50384


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== public donation route =="
cat -n src/app/api/donations/route.ts

echo
echo "== donation schema =="
cat -n src/infrastructure/database/schema/donation.ts

echo
echo "== package scripts =="
python3 - <<'PY'
import json
with open("package.json") as f:
    data=json.load(f)
print(json.dumps(data.get("scripts", {}), indent=2))
PY

echo
echo "== Zod boolean literal behavior probe =="
if [ -f package.json ]; then
  node - <<'JS'
const fs = require('fs');
const p = JSON.parse(fs.readFileSync('package.json','utf8'));
console.log({ zodVersion: p.dependencies?.zod || p.devDependencies?.zod, hasZodInstalled: undefined });
JS
fi

echo
echo "== deterministic schema validation simulation =="
python3 - <<'PY'
# Simulate the two Zod validators relevant to the review claim:
# z.boolean() accepts both false and true.
# z.literal(true) accepts only true and fails missing/false.
samples = [False, True, None, {"confirmation": False}]
print({
    "z.boolean": [s for s in [False, True] if True],
    "z.literal(true) missing false": ("missing key would not be present", False)
})
print("z.boolean accepts confirmation=false:", False in [False, True])
PY

Repository: Smartlify07/Modern-Advocates

Length of output: 6708


Require and transmit payment confirmation.

confirmation: z.boolean() allows false, and onSubmit does not send confirmation to /api/donations. POST /api/donations also does not validate confirmation, so the route creates a pending donation without enforcing the acknowledgement.

Require confirmation === true in the form schema, include it in the request body, and reject missing/false confirmation in src/app/api/donations/route.ts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/donation-form.tsx` at line 46, Update the
donation form schema around confirmation to require a true value, include
confirmation in the onSubmit request body, and add matching validation in the
POST handler for /api/donations so missing or false confirmation is rejected
before creating a pending donation.

100-102: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Correct the donation copy.

Line 101 uses a period after “hope” where the sentence needs a comma.

- Help us bring hope. support, and real impact in communities
+ Help us bring hope, support, and real impact in communities
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

        <p className="text-base">
          Help us bring hope, support, and real impact in communities
        </p>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/donation-form.tsx` around lines 100 - 102,
Update the donation copy in the paragraph rendered by the donation form to
replace the period after “hope” with a comma, preserving the rest of the
sentence.
src/features/marketing/lib/donation-pricing.ts (1)

3-9: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

node - <<'NODE'
const actual = Math.round(9.5 * 0.03 * 100) / 100
if (actual !== 0.29) {
  console.error({ actual, expected: 0.29 })
  process.exit(1)
}
NODE

Repository: Smartlify07/Modern-Advocates

Length of output: 199


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file =="
git ls-files | grep -F 'src/features/marketing/lib/donation-pricing.ts' || true

echo "== file excerpt =="
if [ -f src/features/marketing/lib/donation-pricing.ts ]; then
  cat -n src/features/marketing/lib/donation-pricing.ts
fi

echo "== usages =="
rg -n "computeAdminFee|computeDonationTotal|donation-pricing" src || true

echo "== relevant JS evidence =="
node - <<'NODE'
const ADMIN_FEE_RATE = 0.03
function computeAdminFee(amount) { return Math.round(amount * ADMIN_FEE_RATE * 100) / 100 }
function computeDonationTotal(amount) { return Math.round((amount + computeAdminFee(amount)) * 100) / 100 }

for (const amount of [9.5, 16.5, 33.49, 100.00, 0.01]) {
  console.log(JSON.stringify({ amount, fee: computeAdminFee(amount), total: computeDonationTotal(amount) }))
}

const inputs = [9.5, 9.52, 9.53, 16.5, 33.49]
const failures = []
for (const amount of inputs) {
  const fee = computeAdminFee(amount)
  const cents = fee * 100
  const roundToEvenExpected = Math.round(Math.floor(cents + 0.5)) / 100
  if (fee !== roundToEvenExpected) failures.push(JSON.stringify({ amount, fee, expected: roundToEvenExpected }))
}
console.log("failures=", failures.length)
for (const f of failures) console.log(f)
NODE

Repository: Smartlify07/Modern-Advocates

Length of output: 1958


Calculate fee rounding in integer cents.

JavaScript evaluates 9.50 * 0.03 * 100 as 28.499999999999996, so this code returns $0.28 instead of $0.29. The affected donation total is shown in the form, sent to Stripe, and reused on the success page. Convert the input to cents and compute the fee with integer basis points so the half-cent decision depends on exact cent arithmetic.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/lib/donation-pricing.ts` around lines 3 - 9, Update
computeAdminFee to convert the amount to integer cents and calculate the fee
using integer basis-point arithmetic before converting back to dollars, ensuring
half-cent values round correctly. Keep computeDonationTotal using the corrected
fee result and preserve its existing cent-based total rounding.
src/shared/lib/api-handler.ts (1)

42-42: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 4 'console\.error|logger\.(error|warn)|redact|sanitize|request.?id|correlation' src

Repository: Smartlify07/Modern-Advocates

Length of output: 16794


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- api-handler.ts ---\n'
cat -n src/shared/lib/api-handler.ts

printf '\n--- API route usages of apiFetch/apiHandler ---\n'
rg -n "apiFetch|apiHandler|NextResponse\.error|throw .*Error" src/app src/features | head -n 200

printf '\n--- error class definitions and message sources ---\n'
rg -n "class .*Error|extends .*Error|new \\w+Error\\(|message:" src/shared src/app src/features src/infrastructure | head -n 250

printf '\n--- node dependency versions for logging libraries ---\n'
node - <<'JS'
const fs = require('fs')
const pkg = JSON.parse(fs.readFileSync('package.json','utf8'))
console.log(pkg.dependencies && JSON.stringify(pkg.dependencies, null, 2))
console.log(pkg.devDependencies && JSON.stringify(pkg.devDependencies, null, 2))
JS

Repository: Smartlify07/Modern-Advocates

Length of output: 257


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '::group::api-handler-context\n'
sed -n '1,90p' src/shared/lib/api-handler.ts | cat -n
printf '::endgroup::\n'

printf '::group::all-raw-console-error-calls\n'
python3 - <<'PY'
import pathlib, re
for p in pathlib.Path('src').rglob('*'):
    if p.is_file() and any(p.suffix in {'.ts','.tsx'}):
        text=p.read_text(errors='ignore')
        for i,line in enumerate(text.splitlines(),1):
            if re.search(r'\bconsole\.error\s*\(', line):
                print(f'{p}:{i}:{line.strip()}')
PY
printf '::endgroup::\n'

printf '::group::security-sensitive-data-sources\n'
rg -n "password|secret|api[_-]?key|auth|stripe|donat|enroll|invoice|metadata|pii|email|stripeSecret|billing|card|token|session" src/app src/features src/infrastructure src/shared | head -n 300
printf '::endgroup::\n'

printf '::group::logging-library-config\n'
node - <<'JS'
const fs = require('fs')
const pkg = JSON.parse(fs.readFileSync('package.json','utf8'))
console.log('dependencies:', pkg.dependencies)
console.log('devDependencies:', pkg.devDependencies)
if (fs.existsSync('src/shared/lib/logger.ts')) console.log(fs.readFileSync('src/shared/lib/logger.ts','utf8').slice(0,3000))
else console.log('src/shared/lib/logger.ts absent')
if (fs.existsSync('src/shared/lib/sentry.ts')) console.log(fs.readFileSync('src/shared/lib/sentry.ts','utf8').slice(0,3000))
else console.log('src/shared/lib/sentry.ts absent')
JS
printf '::endgroup::\n'

Repository: Smartlify07/Modern-Advocates

Length of output: 2213


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "--- api-handler.ts ---"
cat -n src/shared/lib/api-handler.ts

echo
echo "--- all console.error calls in TypeScript under src ---"
python3 - <<'PY'
import pathlib, re
for p in pathlib.Path('src').rglob('*'):
    if p.is_file() and p.suffix in {'.ts', '.tsx'}:
        text = p.read_text(errors='ignore')
        for i, line in enumerate(text.splitlines(), 1):
            if re.search(r'\bconsole\.error\s*\(', line):
                print(f'{p}:{i}:{line.strip()}')
PY

echo
echo "--- potential sensitive/data-service error sources ---"
rg -n "throw new .*Error|Error\\(|message|password|secretKey|secret |api-secret|client secret|stripe|donation|enrollment|session|email|token|metadata|pii|billing|card|cardNumber|cardExpiry" src/app src/features src/infrastructure | head -n 400

echo
echo "--- logging-related config files ---"
for f in package.json src/shared/lib/logger.ts src/shared/lib/sentry.ts next.config.* .env* .env.example .env.local; do
  if [ -e "$f" ]; then
    echo "### $f"
    sed -n '1,180p' "$f"
  fi
done

echo
echo "--- api-handler callers ---"
rg -n "apiHandler\\(|apiFetch\\(" src/app src/features | head -n 200

Repository: Smartlify07/Modern-Advocates

Length of output: 50384


Do not log raw caught errors.

console.error(error) at line 42 writes the complete Error object and also sends it to Sentry. API and payment paths process email, donation, enrollment, session, and Stripe transaction data, so error details should use a redacting logger or a trusted production logger with sensitive-field handling.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/shared/lib/api-handler.ts` at line 42, Replace the raw
console.error(error) call in the API handler with the project’s trusted
redacting production logger, ensuring caught errors are logged without exposing
sensitive API, payment, email, enrollment, session, or Stripe transaction
fields.

@Smartlify07
Smartlify07 merged commit 6c42560 into main Aug 9, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant