Fazekit

Code

"use client";
import * as React from "react";
import { MotionConfig, useReducedMotion } from "motion/react";
import { cn } from "@/lib/utils";
import { defaultNonprofitData, type NonprofitData, type Program } from "./data";
import { Footer, Partners, Transparency, Volunteer, type VolunteerRequest } from "./sections/closing";
import { Donate, type DonationRequest } from "./sections/donate";
import { Hero, Impact } from "./sections/hero";
import { Navbar } from "./sections/navbar";
import { Programs, Stories } from "./sections/programs";
import { scrollToId, useMoney } from "./sections/ui";

export type { NonprofitData, DonationRequest, VolunteerRequest };
export { defaultNonprofitData };

export interface NonprofitTemplateProps {
  /** Override any top-level content group (brand, programs, donate…). Missing groups fall back to the demo content. */
  data?: Partial<NonprofitData>;
  /** Called when a donation is submitted. Return a promise to keep the loading state until your payment API answers. */
  onDonate?: (request: DonationRequest) => void | Promise<void>;
  onVolunteer?: (request: VolunteerRequest) => void | Promise<void>;
  className?: string;
}

/**
 * Open Water Fund — a charity landing page.
 * Rippling-water hero, count-up impact stats, funded programs, field stories,
 * a one-time/monthly donation widget with live impact, an animated allocation donut,
 * volunteer sign-up, partner marquee and a footer CTA.
 */
export function NonprofitTemplate({ data, onDonate, onVolunteer, className }: NonprofitTemplateProps) {
  const d: NonprofitData = React.useMemo(() => ({ ...defaultNonprofitData, ...data }), [data]);
  const reduce = useReducedMotion();
  const money = useMoney(d.brand.currency);
  const [designation, setDesignation] = React.useState<Program | null>(null);
  const go = React.useCallback((id: string) => scrollToId(id, reduce), [reduce]);

  return (
    <MotionConfig reducedMotion="user">
      <div className={cn("relative w-full bg-background text-foreground antialiased selection:bg-[#ffd166]/60 selection:text-[#3a2a00]", className)}>
        <Navbar data={d} onDonate={() => go("donate")} />
        <main>
          <Hero data={d} onDonate={() => go("donate")} onImpact={() => go("impact")} />
          <Impact data={d} />
          <Programs
            programs={d.programs}
            money={money}
            onFund={(p) => {
              setDesignation(p);
              go("donate");
            }}
          />
          <Stories stories={d.stories} />
          <Donate data={d} money={money} designation={designation} onDonate={onDonate} />
          <Transparency data={d} />
          <Volunteer data={d} onSignup={onVolunteer} />
          <Partners partners={d.partners} />
        </main>
        <Footer data={d} onDonate={() => go("donate")} onNav={go} />
      </div>
    </MotionConfig>
  );
}

More in Landing Pages

View all →