Donation page UI updates - #138
Conversation
…into ch/donation-page-ui-updtes
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThe donation page now presents founder-focused content and delegates donation form rendering to ChangesDonation marketing flow
Footer styling
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
src/features/marketing/components/donation-support-section.tsx (1)
82-82: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReplace the arbitrary hex background with a design token.
bg-[#ECE8FF]hardcodes a color. The rest of this cohort uses tokens such asbg-ma-surface-2andbg-ma-bg. Add a token for this lavender value in the Tailwind theme and reference it here.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/donation-support-section.tsx` at line 82, Replace the arbitrary bg-[`#ECE8FF`] class on the donation support section with a named design-token background class, and add the corresponding lavender color token to the project’s Tailwind theme. Keep the existing layout and spacing classes unchanged.Source: Coding guidelines
src/features/marketing/components/donation-hero-section.tsx (1)
41-57: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse separate
<p>elements instead of stacked<br />pairs.The wrapper already applies
space-y-5. Splitting the text into individual paragraphs removes the manual<br /> <br />spacing, keeps spacing consistent with the design tokens, and improves screen reader navigation.♻️ Proposed refactor
<div className="mt-[31px] space-y-5 text-base leading-normal text-ma-text sm:text-lg"> + <p>We know what it’s like when illness changes everything.</p> <p> - We know what it’s like when illness changes everything. - <br /> <br /> Our journey with endometriosis affected nearly - every part of our lives—our health, careers, finances, - relationships, and future. Along the way, Jehovah answered our - prayers through the kindness and generosity of others. <br />{" "} - <br /> Modern Advocates was created to extend that same hope.{" "} - <br /> <br /> - Today, we help people facing chronic illness, disability, and - financial hardship discover practical pathways forward through - education, AI, health advocacy, and community support. <br /> - <br /> - ModernAdvocates Inc. is a 501(c)(3) nonprofit organization. EIN: - 42-3785190. All donations are tax-deductible to the full extent - permitted by law. + Our journey with endometriosis affected nearly every part of our + lives—our health, careers, finances, relationships, and future. + Along the way, Jehovah answered our prayers through the kindness + and generosity of others. </p> + <p>Modern Advocates was created to extend that same hope.</p> + <p> + Today, we help people facing chronic illness, disability, and + financial hardship discover practical pathways forward through + education, AI, health advocacy, and community support. + </p> + <p> + ModernAdvocates Inc. is a 501(c)(3) nonprofit organization. EIN: + 42-3785190. All donations are tax-deductible to the full extent + permitted by law. + </p> </div>🤖 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-hero-section.tsx` around lines 41 - 57, In the donation hero text within the component’s paragraph wrapper, split each distinct thought into separate <p> elements and remove all stacked <br /> pairs and paragraph-level manual breaks. Preserve the existing copy and rely on the wrapper’s space-y-5 spacing for consistent layout and screen reader navigation.
🤖 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/features/marketing/components/donation-hero-section.tsx`:
- Around line 24-31: Update the alt text on the Image displaying
melanie-and-will.png to accurately describe both founders, matching the card’s
“Melanie And Will” / “Founders” content instead of naming only Melanie Reyes.
In `@src/features/marketing/components/donation-support-section.tsx`:
- Around line 81-96: Connect DonationSupportSection’s existing form, onSubmit,
and submitting state to DonationForm by passing the required props and rendering
its controls inside a form using form.handleSubmit(onSubmit). Make the Donate
Now button type="submit" and reflect submitting state, ensuring the donation
submission invokes /api/donations.
In `@src/features/marketing/components/footer.tsx`:
- Line 16: Update the footer grid classes in the component containing this div
to remove the arbitrary gap-[140px] value. Replace it with an existing spacing
token, or define and use a semantic theme token if the 140px spacing is
required.
---
Nitpick comments:
In `@src/features/marketing/components/donation-hero-section.tsx`:
- Around line 41-57: In the donation hero text within the component’s paragraph
wrapper, split each distinct thought into separate <p> elements and remove all
stacked <br /> pairs and paragraph-level manual breaks. Preserve the existing
copy and rely on the wrapper’s space-y-5 spacing for consistent layout and
screen reader navigation.
In `@src/features/marketing/components/donation-support-section.tsx`:
- Line 82: Replace the arbitrary bg-[`#ECE8FF`] class on the donation support
section with a named design-token background class, and add the corresponding
lavender color token to the project’s Tailwind theme. Keep the existing layout
and spacing classes unchanged.
🪄 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: b82af8a4-a47a-4fad-a201-b76b6f67e1fc
⛔ Files ignored due to path filters (6)
public/figma-home/downloaded-node-2800-19876.pngis excluded by!**/*.pngpublic/figma-home/downloaded-node-2800-19884.pngis excluded by!**/*.pngpublic/figma-home/downloaded-node-2800-19886.pngis excluded by!**/*.pngpublic/figma-home/downloaded-node-2800-19890.pngis excluded by!**/*.pngpublic/figma-home/downloaded-node-2800-19892.pngis excluded by!**/*.pngpublic/figma-home/downloaded-node-2863-17140.pngis excluded by!**/*.png
📒 Files selected for processing (3)
src/features/marketing/components/donation-hero-section.tsxsrc/features/marketing/components/donation-support-section.tsxsrc/features/marketing/components/footer.tsx
| <Image | ||
| src="/figma-home/melanie-and-will.png" | ||
| alt="Melanie Reyes, founder of ModernAdvocates Inc." | ||
| priority | ||
| className="rounded-card-2 object-cover sm:h-full" | ||
| width={510} | ||
| height={560} | ||
| /> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Update the alt text to match the new image.
The image now shows both founders, and the card below reads "Melanie And Will" / "Founders". The alt text still names only Melanie Reyes as the founder. Screen reader users receive incorrect information.
♿ Proposed fix for the alt text
<Image
src="/figma-home/melanie-and-will.png"
- alt="Melanie Reyes, founder of ModernAdvocates Inc."
+ alt="Melanie and Will, founders of ModernAdvocates Inc."
priority📝 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.
| <Image | |
| src="/figma-home/melanie-and-will.png" | |
| alt="Melanie Reyes, founder of ModernAdvocates Inc." | |
| priority | |
| className="rounded-card-2 object-cover sm:h-full" | |
| width={510} | |
| height={560} | |
| /> | |
| <Image | |
| src="/figma-home/melanie-and-will.png" | |
| alt="Melanie and Will, founders of ModernAdvocates Inc." | |
| priority | |
| className="rounded-card-2 object-cover sm:h-full" | |
| width={510} | |
| height={560} | |
| /> |
🤖 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-hero-section.tsx` around lines 24
- 31, Update the alt text on the Image displaying melanie-and-will.png to
accurately describe both founders, matching the card’s “Melanie And Will” /
“Founders” content instead of naming only Melanie Reyes.
| return ( | ||
| <section className="bg-white py-12.5 text-ma-text lg:py-25"> | ||
| <div className="mx-auto grid items-start gap-12 px-4 lg:max-w-7xl lg:grid-cols-2 lg:gap-6 lg:px-25 2xl:max-w-360 2xl:px-50"> | ||
| <section className="bg-[#ECE8FF] py-12.5 text-ma-text lg:py-25"> | ||
| <div className="mx-auto grid items-center gap-12 px-4 lg:max-w-7xl lg:grid-cols-2 lg:gap-6 lg:px-25 2xl:max-w-360 2xl:px-50"> | ||
| <div className="pt-0 lg:pt-2"> | ||
| <h2 className="font-sans text-[28px]/[100%] leading-[1.12] font-extrabold text-balance text-primary lg:text-[60px]/[70px] lg:tracking-tight-xl"> | ||
| Support us and make a difference for the future! | ||
| <h2 className="font-sans text-3xl leading-[1.12] font-extrabold text-balance text-primary sm:text-5xl sm:tracking-tight-xl"> | ||
| Invest in Hope | ||
| </h2> | ||
| <p className="mt-[30px] max-w-[506px] text-base leading-normal text-primary lg:text-lg"> | ||
| Together, we can make a real impact in communities around the world. | ||
| Help us bring hope and support. | ||
| Your gift helps fund: <br /> <br /> | ||
| AI & Digital Skills Education, Health Advocacy, Patient Resource | ||
| Navigation, Workforce Readiness, Chronic Illness Support, and | ||
| Endometriosis Education. | ||
| </p> | ||
| </div> | ||
|
|
||
| <form | ||
| onSubmit={form.handleSubmit(onSubmit)} | ||
| className="flex w-full flex-col gap-[30px] rounded-card-2 border border-ma-border-light bg-ma-surface-2 px-4 pt-[30px] pb-7 sm:px-[30px] lg:px-7" | ||
| > | ||
| <div className="border-b border-ma-border-light pb-2.5"> | ||
| <h3 className="text-2xl leading-normal font-bold text-black"> | ||
| Make Your Donation | ||
| </h3> | ||
| </div> | ||
|
|
||
| <Controller | ||
| control={form.control} | ||
| name="donationType" | ||
| render={({ field, fieldState }) => ( | ||
| <Field data-invalid={fieldState.invalid}> | ||
| <legend className="text-xl leading-normal font-semibold text-black"> | ||
| Type of Donation | ||
| </legend> | ||
|
|
||
| <div className="grid gap-3 sm:grid-cols-3"> | ||
| {donationTypes.map((type) => ( | ||
| <label | ||
| key={type} | ||
| className="flex min-w-0 items-start gap-2 text-base leading-normal text-muted-foreground" | ||
| > | ||
| <input | ||
| type="radio" | ||
| name={field.name} | ||
| value={type} | ||
| checked={field.value === type} | ||
| onChange={() => field.onChange(type)} | ||
| aria-invalid={fieldState.invalid} | ||
| className="mt-0.5 size-5 shrink-0 accent-ma-glow-violet" | ||
| /> | ||
| <span>{type}</span> | ||
| </label> | ||
| ))} | ||
| </div> | ||
| {fieldState.invalid && <FieldError errors={[fieldState.error]} />} | ||
| </Field> | ||
| )} | ||
| /> | ||
|
|
||
| {showAmountSelector ? ( | ||
| <Controller | ||
| control={form.control} | ||
| name="amount" | ||
| render={({ field, fieldState }) => ( | ||
| <Field data-invalid={fieldState.invalid}> | ||
| <label className="text-xl leading-normal font-semibold text-black"> | ||
| Select Donation Amount | ||
| </label> | ||
| <div className="flex flex-col gap-2"> | ||
| {donationAmounts.map((amount) => ( | ||
| <label | ||
| key={amount} | ||
| className={`relative cursor-pointer rounded-[6px] ${ | ||
| field.value === amount | ||
| ? "bg-linear-[90deg] from-[#4F7CF7] from-[0%] to-[#7B5CFF] to-[68.27%] p-[1.1px] pb-[1.3px]" | ||
| : "border border-border" | ||
| }`} | ||
| > | ||
| <div | ||
| className={`flex items-center justify-between rounded-[5px] bg-white px-4 py-2.5 text-base/[100%] font-medium ${ | ||
| field.value === amount | ||
| ? "text-ma-text" | ||
| : "text-ma-text" | ||
| }`} | ||
| > | ||
| <span>${amount}</span> | ||
| <input | ||
| type="radio" | ||
| name={field.name} | ||
| value={amount} | ||
| checked={field.value === amount} | ||
| onChange={() => field.onChange(amount)} | ||
| aria-invalid={fieldState.invalid} | ||
| className="size-5 accent-ma-glow-violet" | ||
| /> | ||
| </div> | ||
| </label> | ||
| ))} | ||
| </div> | ||
| {fieldState.invalid && <FieldError errors={[fieldState.error]} />} | ||
| </Field> | ||
| )} | ||
| /> | ||
| ) : ( | ||
| <Controller | ||
| control={form.control} | ||
| name="amount" | ||
| render={({ field, fieldState }) => ( | ||
| <Field data-invalid={fieldState.invalid}> | ||
| <label htmlFor={field.name} className="sr-only"> | ||
| Donation amount | ||
| </label> | ||
| <div className="relative"> | ||
| <Input | ||
| id={field.name} | ||
| type="number" | ||
| inputMode="decimal" | ||
| placeholder="Enter Amount" | ||
| value={field.value || ""} | ||
| onChange={(e) => field.onChange(parseFloat(e.target.value) || 0)} | ||
| aria-invalid={fieldState.invalid} | ||
| className="h-10 rounded-[6px] border-border bg-white px-4 py-2.5 pr-10 text-base placeholder:text-muted-foreground" | ||
| /> | ||
| <span | ||
| className="pointer-events-none absolute top-1/2 right-4 -translate-y-1/2 text-xl leading-none font-bold text-ma-text" | ||
| aria-hidden="true" | ||
| > | ||
| $ | ||
| </span> | ||
| </div> | ||
| {fieldState.invalid && <FieldError errors={[fieldState.error]} />} | ||
| </Field> | ||
| )} | ||
| /> | ||
| )} | ||
|
|
||
| <div className="flex flex-col gap-4"> | ||
| <h3 className="text-xl leading-normal font-semibold text-black"> | ||
| Personal Info | ||
| </h3> | ||
|
|
||
| <Controller | ||
| control={form.control} | ||
| name="donorName" | ||
| render={({ field, fieldState }) => ( | ||
| <Field data-invalid={fieldState.invalid}> | ||
| <FieldLabel htmlFor={field.name}> | ||
| Full Name | ||
| </FieldLabel> | ||
| <Input | ||
| {...field} | ||
| id={field.name} | ||
| autoComplete="name" | ||
| placeholder="Enter full name" | ||
| aria-invalid={fieldState.invalid} | ||
| className="h-10 rounded-md border-border bg-white px-4 py-2.5 text-base placeholder:text-muted-foreground" | ||
| /> | ||
| {fieldState.invalid && <FieldError errors={[fieldState.error]} />} | ||
| </Field> | ||
| )} | ||
| /> | ||
|
|
||
| <Controller | ||
| control={form.control} | ||
| name="donorEmail" | ||
| render={({ field, fieldState }) => ( | ||
| <Field data-invalid={fieldState.invalid}> | ||
| <FieldLabel htmlFor={field.name}> | ||
| </FieldLabel> | ||
| <Input | ||
| {...field} | ||
| id={field.name} | ||
| type="email" | ||
| autoComplete="email" | ||
| placeholder="Enter email" | ||
| aria-invalid={fieldState.invalid} | ||
| className="h-10 rounded-md border-border bg-white px-4 py-2.5 text-base placeholder:text-muted-foreground" | ||
| /> | ||
| {fieldState.invalid && <FieldError errors={[fieldState.error]} />} | ||
| </Field> | ||
| )} | ||
| /> | ||
| </div> | ||
|
|
||
| <Controller | ||
| control={form.control} | ||
| name="confirmation" | ||
| render={({ field, fieldState }) => ( | ||
| <Field data-invalid={fieldState.invalid} orientation="horizontal"> | ||
| <input | ||
| type="checkbox" | ||
| id={field.name} | ||
| name={field.name} | ||
| checked={field.value === true} | ||
| onChange={(e) => field.onChange(e.target.checked)} | ||
| aria-invalid={fieldState.invalid} | ||
| className="mt-1 size-[18px] shrink-0 rounded border-border bg-white accent-ma-text" | ||
| /> | ||
| <label htmlFor={field.name} className="text-base leading-normal text-muted-foreground"> | ||
| By submitting this form, you confirm the accuracy of the donation | ||
| amount and authorize the payment processing via the checkout page. | ||
| </label> | ||
| {fieldState.invalid && <FieldError errors={[fieldState.error]} />} | ||
| </Field> | ||
| )} | ||
| /> | ||
|
|
||
| <MarketingButton | ||
| type="submit" | ||
| disabled={submitting} | ||
| className="w-full" | ||
| > | ||
| {submitting && <LoaderCircle className="size-4 animate-spin" aria-hidden="true" />} | ||
| Donate Now | ||
| <ArrowRight | ||
| className="size-5 transition-transform duration-300 group-hover:rotate-[-30deg]" | ||
| aria-hidden="true" | ||
| /> | ||
| </MarketingButton> | ||
| </form> | ||
| <DonationForm /> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🔴 Critical
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Verify DonationForm props/usage and confirm /api/donations callers.
set -euo pipefail
echo "=== DonationForm definition and props ==="
fd -t f 'donation-form.tsx' --exec cat -n {}
echo "=== All DonationForm usages ==="
rg -nP --type=tsx --type=ts -C4 '<DonationForm\b|from ["'"'"'].*donation-form["'"'"']'
echo "=== Callers of /api/donations ==="
rg -nP -C6 "['\"\`]/api/donations"
echo "=== Any <form> element in the donation feature ==="
rg -nP -C3 '<form\b' --glob '**/donation*'Repository: Smartlify07/Modern-Advocates
Length of output: 5446
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== donation-support-section outline ==="
ast-grep outline src/features/marketing/components/donation-support-section.tsx || true
echo "=== donation-support-section relevant source ==="
cat -n src/features/marketing/components/donation-support-section.tsx | sed -n '1,130p'
echo "=== DonationForm usage and donationForm import search ==="
rg -n --glob '**/*.{ts,tsx}' -C3 '<DonationForm\b|donation-form|donationTypes|donationFormSchema|useForm|api/donations|authorize-checkbox|custom-amount' src
echo "=== form/button submit wiring in donation-related files ==="
rg -n --glob '**/*.{ts,tsx}' -C2 '<form\b|type="submit"|onClick=|onSubmit=|donation.*submit|Donate Now|authorize-checkbox|custom-amount' src/features/marketing/components src/features --glob '!**/node_modules/**'Repository: Smartlify07/Modern-Advocates
Length of output: 50384
Wire the donation form to its submission handler.
DonationForm renders standalone fields and a Donate Now button, but that button is not inside a <form>, has no type="submit", and has no onClick. DonationSupportSection creates form, onSubmit, and submitting, but only renders <DonationForm /> with no props. As a result, users cannot submit, onSubmit is unreachable, and /api/donations is not invoked from either donation page.
Move the form contract into DonationForm, or pass form, onSubmit, and submitting as props and render the controls inside <form onSubmit={form.handleSubmit(onSubmit)}>, with the submit button bound as type="submit".
[high_effort_and_HIGH_reward]
🤖 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-support-section.tsx` around lines
81 - 96, Connect DonationSupportSection’s existing form, onSubmit, and
submitting state to DonationForm by passing the required props and rendering its
controls inside a form using form.handleSubmit(onSubmit). Make the Donate Now
button type="submit" and reflect submitting state, ensuring the donation
submission invokes /api/donations.
| <footer className="overflow-hidden bg-white text-ma-text"> | ||
| <div className="relative mx-auto min-h-125 px-4 pt-12.5 lg:max-w-7xl lg:px-25 lg:pt-17.5 2xl:max-w-360"> | ||
| <div className="grid gap-10 md:grid-cols-[0.9fr_0.6fr_1.5fr] lg:gap-10 xl:grid-cols-[254px_180px_1fr] xl:justify-between xl:gap-[154px] 2xl:gap-50"> | ||
| <div className="grid gap-10 md:grid-cols-[0.9fr_0.6fr_1.5fr] lg:gap-10 xl:grid-cols-[254px_180px_1fr] xl:justify-between xl:gap-[140px] 2xl:gap-50"> |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use a spacing token instead of gap-[140px].
This class introduces an arbitrary spacing value. The repository guidelines prohibit arbitrary spacing. Reuse an existing spacing token. If 140px is required, define a semantic theme token and reference it here.
🤖 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/footer.tsx` at line 16, Update the footer
grid classes in the component containing this div to remove the arbitrary
gap-[140px] value. Replace it with an existing spacing token, or define and use
a semantic theme token if the 140px spacing is required.
Source: Coding guidelines
UI updates for the public donation page.
Changes
Summary by CodeRabbit
New Features
Style