Seed: nonprofit template (15 files)
This commit is contained in:
@@ -0,0 +1,212 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
import { Heart, HandHeart, Megaphone, Calendar, MapPin, Clock, ArrowRight, DollarSign, Users, Sparkles } from "lucide-react";
|
||||||
|
import { useSaasMutation } from "@/hooks/use-tygarun";
|
||||||
|
import Header from "@/components/Header";
|
||||||
|
import Footer from "@/components/Footer";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
export default function GetInvolvedPage() {
|
||||||
|
const [donationAmount, setDonationAmount] = useState("50");
|
||||||
|
const [customAmount, setCustomAmount] = useState("");
|
||||||
|
const [donating, setDonating] = useState(false);
|
||||||
|
const [applying, setApplying] = useState(false);
|
||||||
|
const amounts = ["25", "50", "100"];
|
||||||
|
const { mutate: donate } = useSaasMutation("billing", "/checkout");
|
||||||
|
const { mutate: applyVolunteer } = useSaasMutation("crm", "/leads");
|
||||||
|
|
||||||
|
const handleDonate = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const form = e.currentTarget as HTMLFormElement;
|
||||||
|
const dollars = Number(donationAmount === "custom" ? customAmount : donationAmount);
|
||||||
|
if (!dollars || dollars < 1) return;
|
||||||
|
const email = (new FormData(form).get("email") as string) || "";
|
||||||
|
setDonating(true);
|
||||||
|
try {
|
||||||
|
const res = await donate({ plan: "Donation", amount: Math.round(dollars * 100), email });
|
||||||
|
if (res?.url && res.url !== "#") { window.location.href = res.url; return; }
|
||||||
|
toast.success(`Thank you for your generous $\${dollars} donation!`);
|
||||||
|
} catch {
|
||||||
|
toast.error("Could not start checkout. Please try again.");
|
||||||
|
} finally {
|
||||||
|
setDonating(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleVolunteer = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const form = e.currentTarget as HTMLFormElement;
|
||||||
|
const body = Object.fromEntries(new FormData(form).entries());
|
||||||
|
setApplying(true);
|
||||||
|
try {
|
||||||
|
await applyVolunteer({ ...body, interest: "volunteer" });
|
||||||
|
toast.success("Application received! We will be in touch within 48 hours.");
|
||||||
|
form.reset();
|
||||||
|
} catch {
|
||||||
|
toast.error("Could not submit application. Please try again.");
|
||||||
|
} finally {
|
||||||
|
setApplying(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const events = [
|
||||||
|
{ title: "Annual Charity Gala", date: "June 15, 2026", location: "New York, NY", desc: "An evening of inspiration, live music, and fundraising. Join us to celebrate our impact and support the next chapter." },
|
||||||
|
{ title: "Run for Water 5K", date: "August 22, 2026", location: "San Francisco, CA", desc: "Lace up for clean water. Every registration funds one month of clean water for a family in need." },
|
||||||
|
{ title: "Global Volunteer Summit", date: "October 10, 2026", location: "Virtual", desc: "Connect with volunteers worldwide, hear from program leaders, and discover new ways to make an impact." },
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-white dark:bg-slate-950">
|
||||||
|
<Header />
|
||||||
|
|
||||||
|
{/* ── Hero ── */}
|
||||||
|
<section className="relative pt-32 pb-20 bg-gradient-to-br from-emerald-700 via-emerald-600 to-teal-500">
|
||||||
|
<div className="mx-auto max-w-4xl px-6 text-center">
|
||||||
|
<p className="text-sm font-semibold uppercase tracking-widest text-white/70 mb-4 animate-fade-up">Get Involved</p>
|
||||||
|
<h1 className="text-4xl sm:text-5xl font-extrabold text-white mb-6 animate-fade-up">Your Support Changes Lives</h1>
|
||||||
|
<p className="text-lg text-white/85 max-w-2xl mx-auto animate-fade-up">Whether you donate, volunteer, or fundraise, every action creates ripples of positive change in communities around the world.</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* ── Three Ways ── */}
|
||||||
|
<section className="py-20 bg-white dark:bg-slate-950">
|
||||||
|
<div className="mx-auto max-w-7xl px-6">
|
||||||
|
<div className="grid lg:grid-cols-3 gap-10">
|
||||||
|
|
||||||
|
{/* Donate */}
|
||||||
|
<Card className="bg-white dark:bg-slate-900 border-slate-200/60 dark:border-slate-800/60 rounded-2xl shadow-lg animate-fade-up">
|
||||||
|
<CardContent className="p-8">
|
||||||
|
<div className="w-12 h-12 rounded-xl bg-emerald-100 dark:bg-emerald-900/30 flex items-center justify-center mb-4">
|
||||||
|
<Heart className="h-6 w-6 text-emerald-600 fill-current" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl font-bold text-slate-900 dark:text-white mb-2">Make a Donation</h3>
|
||||||
|
<p className="text-sm text-muted-foreground mb-6">Every dollar goes directly to the communities we serve. 95% of funds reach programs.</p>
|
||||||
|
<form onSubmit={handleDonate} className="space-y-4">
|
||||||
|
<div className="grid grid-cols-4 gap-2">
|
||||||
|
{amounts.map((a) => (
|
||||||
|
<Button key={a} type="button" variant={donationAmount === a ? "default" : "outline"} className={`rounded-full \${donationAmount === a ? "bg-emerald-600 hover:bg-emerald-700 text-white" : ""}`} onClick={() => { setDonationAmount(a); setCustomAmount(""); }}>
|
||||||
|
${a}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
<Button type="button" variant={donationAmount === "custom" ? "default" : "outline"} className={`rounded-full text-xs \${donationAmount === "custom" ? "bg-emerald-600 hover:bg-emerald-700 text-white" : ""}`} onClick={() => setDonationAmount("custom")}>
|
||||||
|
Other
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
{donationAmount === "custom" && (
|
||||||
|
<div className="relative">
|
||||||
|
<DollarSign className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
|
||||||
|
<Input type="number" min="1" placeholder="Enter amount" value={customAmount} onChange={(e) => setCustomAmount(e.target.value)} className="pl-9 rounded-full" required />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<Input type="email" name="email" placeholder="Your email" required className="rounded-full" />
|
||||||
|
<Button type="submit" disabled={donating} className="w-full bg-emerald-600 hover:bg-emerald-700 text-white rounded-full active:scale-[0.97] transition-all">
|
||||||
|
Donate Now <Heart className="ml-2 h-4 w-4 fill-current" />
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* Volunteer */}
|
||||||
|
<Card className="bg-white dark:bg-slate-900 border-slate-200/60 dark:border-slate-800/60 rounded-2xl shadow-lg animate-fade-up">
|
||||||
|
<CardContent className="p-8">
|
||||||
|
<div className="w-12 h-12 rounded-xl bg-teal-100 dark:bg-teal-900/30 flex items-center justify-center mb-4">
|
||||||
|
<HandHeart className="h-6 w-6 text-teal-600" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl font-bold text-slate-900 dark:text-white mb-2">Volunteer With Us</h3>
|
||||||
|
<p className="text-sm text-muted-foreground mb-6">Join our global network of volunteers making a hands-on difference in communities.</p>
|
||||||
|
<form onSubmit={handleVolunteer} className="space-y-4">
|
||||||
|
<div className="grid grid-cols-2 gap-2">
|
||||||
|
<div>
|
||||||
|
<Label className="text-xs">First Name</Label>
|
||||||
|
<Input name="firstName" placeholder="Jane" required className="rounded-full mt-1" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label className="text-xs">Last Name</Label>
|
||||||
|
<Input name="lastName" placeholder="Smith" required className="rounded-full mt-1" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label className="text-xs">Email</Label>
|
||||||
|
<Input type="email" name="email" placeholder="jane@example.com" required className="rounded-full mt-1" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label className="text-xs">Why do you want to volunteer?</Label>
|
||||||
|
<Textarea name="message" placeholder="Tell us about your skills and motivation..." className="rounded-xl mt-1 min-h-[80px]" />
|
||||||
|
</div>
|
||||||
|
<Button type="submit" disabled={applying} className="w-full bg-teal-600 hover:bg-teal-700 text-white rounded-full active:scale-[0.97] transition-all">
|
||||||
|
Apply to Volunteer <HandHeart className="ml-2 h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* Fundraise */}
|
||||||
|
<Card className="bg-white dark:bg-slate-900 border-slate-200/60 dark:border-slate-800/60 rounded-2xl shadow-lg animate-fade-up">
|
||||||
|
<CardContent className="p-8">
|
||||||
|
<div className="w-12 h-12 rounded-xl bg-amber-100 dark:bg-amber-900/30 flex items-center justify-center mb-4">
|
||||||
|
<Megaphone className="h-6 w-6 text-amber-600" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl font-bold text-slate-900 dark:text-white mb-2">Start a Fundraiser</h3>
|
||||||
|
<p className="text-sm text-muted-foreground mb-6">Rally your friends, family, or company to raise funds for a cause you care about.</p>
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="bg-emerald-50/50 dark:bg-slate-800 rounded-xl p-4 space-y-3">
|
||||||
|
{[
|
||||||
|
{ icon: Sparkles, text: "Create a personal fundraising page in minutes" },
|
||||||
|
{ icon: Users, text: "Share with your network and track progress" },
|
||||||
|
{ icon: Heart, text: "100% of funds raised go to your chosen program" },
|
||||||
|
].map((item, i) => (
|
||||||
|
<div key={i} className="flex items-start gap-3">
|
||||||
|
<item.icon className="h-5 w-5 text-emerald-600 mt-0.5 shrink-0" />
|
||||||
|
<p className="text-sm text-slate-700 dark:text-slate-300">{item.text}</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<Button className="w-full bg-amber-500 hover:bg-amber-600 text-white rounded-full active:scale-[0.97] transition-all" onClick={() => toast.success("Redirecting to fundraiser setup...")}>
|
||||||
|
Start Fundraising <ArrowRight className="ml-2 h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* ── Upcoming Events ── */}
|
||||||
|
<section className="py-20 bg-emerald-50/50 dark:bg-slate-900">
|
||||||
|
<div className="mx-auto max-w-7xl px-6">
|
||||||
|
<div className="text-center mb-14 animate-fade-up">
|
||||||
|
<p className="text-sm font-semibold uppercase tracking-widest text-emerald-600 mb-2">Events</p>
|
||||||
|
<h2 className="text-3xl font-bold text-slate-900 dark:text-white">Upcoming Events</h2>
|
||||||
|
</div>
|
||||||
|
<div className="grid md:grid-cols-3 gap-8">
|
||||||
|
{events.map((ev, i) => (
|
||||||
|
<Card key={i} className="bg-white dark:bg-slate-800 border-slate-200/60 dark:border-slate-700/60 rounded-2xl hover:shadow-lg transition-all animate-fade-up">
|
||||||
|
<CardContent className="p-6">
|
||||||
|
<div className="flex items-center gap-2 text-xs text-muted-foreground mb-3">
|
||||||
|
<Calendar className="h-3.5 w-3.5 text-emerald-600" />
|
||||||
|
<span>{ev.date}</span>
|
||||||
|
<span className="text-slate-300 dark:text-slate-600">|</span>
|
||||||
|
<MapPin className="h-3.5 w-3.5 text-emerald-600" />
|
||||||
|
<span>{ev.location}</span>
|
||||||
|
</div>
|
||||||
|
<h3 className="font-bold text-lg text-slate-900 dark:text-white mb-2">{ev.title}</h3>
|
||||||
|
<p className="text-sm text-muted-foreground mb-4">{ev.desc}</p>
|
||||||
|
<Button variant="outline" size="sm" className="rounded-full border-emerald-200 text-emerald-600 hover:bg-emerald-50 dark:border-emerald-800 dark:hover:bg-emerald-900/20">
|
||||||
|
Register <ArrowRight className="ml-1 h-3.5 w-3.5" />
|
||||||
|
</Button>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user